mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-19 00:41:43 +00:00
Compare commits
512 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
35eb90c135 | ||
|
|
761f79385a | ||
|
|
554bda3332 | ||
|
|
2a968df779 | ||
|
|
30ccd13b69 | ||
|
|
60c09ea51f | ||
|
|
65eab93527 | ||
|
|
a226ad8509 | ||
|
|
31f4fd70ce | ||
|
|
7275ab9837 | ||
|
|
5b3facc63b | ||
|
|
0f313fb9ab | ||
|
|
05b7593e66 | ||
|
|
1b85066d26 | ||
|
|
e93b64f58d | ||
|
|
f0a18f31e7 | ||
|
|
29c82527a5 | ||
|
|
c165dc5e50 | ||
|
|
42da07396c | ||
|
|
20e6c04059 | ||
|
|
ff5d3e5b36 | ||
|
|
6cc68ab503 | ||
|
|
068465146b | ||
|
|
3bcf8057d4 | ||
|
|
8039a6c525 | ||
|
|
558c020cca | ||
|
|
7797da78f5 | ||
|
|
0ab81d768f | ||
|
|
1cee5ccb93 | ||
|
|
3ce01b5ac2 | ||
|
|
e6aa8f3ff4 | ||
|
|
9d7b087972 | ||
|
|
bb184ed481 | ||
|
|
b9b31069cc | ||
|
|
d0cf4e8882 | ||
|
|
02fb850761 | ||
|
|
ac8177e10d | ||
|
|
2eb5c54476 | ||
|
|
0e206e69cf | ||
|
|
b1357cace7 | ||
|
|
37202b6f28 | ||
|
|
2ac0d52960 | ||
|
|
dbe1e6f466 | ||
|
|
a61fcbd68d | ||
|
|
fe597eeba1 | ||
|
|
e213a47efd | ||
|
|
dcb96cb50c | ||
|
|
60d48fec57 | ||
|
|
ee8475d21f | ||
|
|
f47e318131 | ||
|
|
cb66bcca3c | ||
|
|
73302f6162 | ||
|
|
cba21a768f | ||
|
|
822e75ec45 | ||
|
|
108ddfa1b4 | ||
|
|
d4c8ee5915 | ||
|
|
ab9647ff5b | ||
|
|
6666d3be42 | ||
|
|
795086b4cf | ||
|
|
56765cf49a | ||
|
|
bf7012fa2d | ||
|
|
10e8fdb724 | ||
|
|
790dc552ca | ||
|
|
0ec8ed6c05 | ||
|
|
832693617f | ||
|
|
772ef8f961 | ||
|
|
95b6cd2dd9 | ||
|
|
ce1ac17dfb | ||
|
|
b2f7a6b651 | ||
|
|
bedbef7999 | ||
|
|
bc159a92a7 | ||
|
|
f50d710a5e | ||
|
|
bc8f68bec7 | ||
|
|
32c62449be | ||
|
|
6190fcb237 | ||
|
|
012d93b2bd | ||
|
|
222669dc2c | ||
|
|
abe25b795b | ||
|
|
354185189c | ||
|
|
f14fe434a1 | ||
|
|
e874ba9313 | ||
|
|
96348e835a | ||
|
|
d91796f8d2 | ||
|
|
9abce8eb06 | ||
|
|
8b4508ad53 | ||
|
|
5b7dd186d2 | ||
|
|
6ea13ea8f3 | ||
|
|
44bcf7fb4d | ||
|
|
c7a1dfc0bc | ||
|
|
a12bb447e4 | ||
|
|
c4bd54ef44 | ||
|
|
f9a11cce5e | ||
|
|
6008671c30 | ||
|
|
7b952d599d | ||
|
|
93cdf68694 | ||
|
|
0c6f24562f | ||
|
|
bdc1cab013 | ||
|
|
3259cffc63 | ||
|
|
67b59f2b31 | ||
|
|
1ce24a7a2f | ||
|
|
635882a9f7 | ||
|
|
71a22861eb | ||
|
|
9cb69c5b46 | ||
|
|
5e08bb28f8 | ||
|
|
ea4d1a39e1 | ||
|
|
31b588d961 | ||
|
|
0b80d566ad | ||
|
|
f8294e689b | ||
|
|
b78f115fcf | ||
|
|
b468c51251 | ||
|
|
023c088290 | ||
|
|
8a11d13a39 | ||
|
|
daa81c64a7 | ||
|
|
e20d96ea4e | ||
|
|
a76d006a07 | ||
|
|
24c031d692 | ||
|
|
6b4eecf5fe | ||
|
|
ccdd0fbdb2 | ||
|
|
5c6b8a0f45 | ||
|
|
67d2fed685 | ||
|
|
d8f11eb149 | ||
|
|
b2ae75acd8 | ||
|
|
4f951789fe | ||
|
|
005c4c5beb | ||
|
|
34f6b3f4c0 | ||
|
|
f7a93713fa | ||
|
|
8c2ff94d70 | ||
|
|
d003ec2dc9 | ||
|
|
8e7cc3fe78 | ||
|
|
6c8f6cf479 | ||
|
|
e37ecd33ae | ||
|
|
57c5523d67 | ||
|
|
7b9c6ebc2f | ||
|
|
9a515c80f8 | ||
|
|
5b73c17f25 | ||
|
|
b8c1024261 | ||
|
|
2622c6c291 | ||
|
|
f66ae59992 | ||
|
|
5e97c81d80 | ||
|
|
f79b7a058a | ||
|
|
e49494830f | ||
|
|
b67d049ac2 | ||
|
|
70102a60b7 | ||
|
|
6dcd2b0e2c | ||
|
|
ce3973435e | ||
|
|
3fcfc8ea72 | ||
|
|
6ceafe3cd0 | ||
|
|
b058dcf64e | ||
|
|
0b9307fdf3 | ||
|
|
39be812b2e | ||
|
|
21e957ee42 | ||
|
|
e0bc97f66b | ||
|
|
3df44c874d | ||
|
|
a58dbec8aa | ||
|
|
9a8067465c | ||
|
|
ffa4b907c0 | ||
|
|
3d1ca856b2 | ||
|
|
5f85457a97 | ||
|
|
4ebae17123 | ||
|
|
fa85fbfc1c | ||
|
|
f62e23f1af | ||
|
|
5443fdabc1 | ||
|
|
c0e36df9d8 | ||
|
|
8c4d9f5415 | ||
|
|
45201d15fc | ||
|
|
845aba33fe | ||
|
|
500c43fb84 | ||
|
|
5891628112 | ||
|
|
b37b68daaf | ||
|
|
0e83c65d27 | ||
|
|
6f6c6da9f5 | ||
|
|
1894219ef6 | ||
|
|
77a9949bbf | ||
|
|
a4c9e4ec28 | ||
|
|
8ed2059074 | ||
|
|
59507b12dc | ||
|
|
5d39bf8065 | ||
|
|
841ef91c0f | ||
|
|
1b66ead49d | ||
|
|
db2c3dddd7 | ||
|
|
82b2170feb | ||
|
|
8280b7e3af | ||
|
|
5510960068 | ||
|
|
df10652183 | ||
|
|
bf5388393e | ||
|
|
b7bc1ea745 | ||
|
|
708009cd20 | ||
|
|
3cce61b89f | ||
|
|
565e1f3e79 | ||
|
|
1853f7b6b7 | ||
|
|
c5a0497124 | ||
|
|
f5446c7409 | ||
|
|
3e049e02f0 | ||
|
|
2da64d15f6 | ||
|
|
f04d95e50f | ||
|
|
d748c67a54 | ||
|
|
55a7f2b4ad | ||
|
|
486fa9c696 | ||
|
|
e3dd1c5d77 | ||
|
|
7dc7c71b58 | ||
|
|
5f33d6af12 | ||
|
|
94843adb8f | ||
|
|
9bcff37b93 | ||
|
|
326aecc9a0 | ||
|
|
00228678d4 | ||
|
|
ff39a96cee | ||
|
|
5ccad2e8a4 | ||
|
|
629e95776a | ||
|
|
6858a57f72 | ||
|
|
0ebe32823a | ||
|
|
384d00f9e6 | ||
|
|
1f6850adf2 | ||
|
|
7508aada93 | ||
|
|
f5b4be16db | ||
|
|
e6f5c93ab1 | ||
|
|
39f46ceab6 | ||
|
|
d93aa2b6b2 | ||
|
|
114ddaf81f | ||
|
|
f22d0961e3 | ||
|
|
3262c2badb | ||
|
|
96d40192ae | ||
|
|
ed30d5d40e | ||
|
|
2b6811eddb | ||
|
|
1d695a1660 | ||
|
|
509819d83f | ||
|
|
2ad15cae19 | ||
|
|
931b8ceefd | ||
|
|
0b3821eba3 | ||
|
|
6f159d1426 | ||
|
|
a769f1f227 | ||
|
|
c5186d8159 | ||
|
|
9ebd23d61e | ||
|
|
f6e311ef86 | ||
|
|
f33bd9f050 | ||
|
|
1c1e0c9a6a | ||
|
|
ea9bb651a3 | ||
|
|
cc07425182 | ||
|
|
16b34cce20 | ||
|
|
669127e49c | ||
|
|
9dc30797e4 | ||
|
|
f6b844ea30 | ||
|
|
a72f809911 | ||
|
|
916596cb01 | ||
|
|
5509a8e968 | ||
|
|
0be6b64756 | ||
|
|
936627bd94 | ||
|
|
8e333c0aad | ||
|
|
d4430b765e | ||
|
|
75438ab2ce | ||
|
|
989df1b461 | ||
|
|
dbc33b61e1 | ||
|
|
79f8c5644a | ||
|
|
9440edf2b5 | ||
|
|
73a30182c3 | ||
|
|
36ea865edc | ||
|
|
cbe05e7e8a | ||
|
|
d04eb35465 | ||
|
|
02264db69c | ||
|
|
2a76c996eb | ||
|
|
a3820bbdfa | ||
|
|
a83fb47933 | ||
|
|
4b0ed910ee | ||
|
|
103c1b121c | ||
|
|
6635ea75ee | ||
|
|
cfe23c5cd0 | ||
|
|
4bde2654e2 | ||
|
|
4f034e6c14 | ||
|
|
acf960f729 | ||
|
|
2d3dac99f0 | ||
|
|
07c86e0cd5 | ||
|
|
46ad95512e | ||
|
|
5bce489b98 | ||
|
|
55af553acc | ||
|
|
c59f9cea5f | ||
|
|
3fc89c84d6 | ||
|
|
2c50937975 | ||
|
|
f3ad927f45 | ||
|
|
05c25deb7b | ||
|
|
d726591ce4 | ||
|
|
2ff694fa49 | ||
|
|
53816155ba | ||
|
|
a38f183a98 | ||
|
|
b3398dca39 | ||
|
|
2c311013d4 | ||
|
|
c10f2003c5 | ||
|
|
63cfa64fb3 | ||
|
|
2402c2bad7 | ||
|
|
f4eedf597f | ||
|
|
bb0b207d2f | ||
|
|
7bd69e591c | ||
|
|
ec9738245d | ||
|
|
46303a8221 | ||
|
|
d169d6be9e | ||
|
|
4e183eb104 | ||
|
|
84c185803d | ||
|
|
0e3b0f3da7 | ||
|
|
7f839b87ce | ||
|
|
45b766a5dc | ||
|
|
56d782b16c | ||
|
|
2b4894038e | ||
|
|
f97d16073a | ||
|
|
55a844a3e1 | ||
|
|
10deba8546 | ||
|
|
a9f0e46680 | ||
|
|
aa90645865 | ||
|
|
81c2c8a7de | ||
|
|
e8d6f8a2c1 | ||
|
|
1b266717a8 | ||
|
|
fb8f3bd06b | ||
|
|
846d8def00 | ||
|
|
d6ac6e512b | ||
|
|
2271570860 | ||
|
|
885744d7e1 | ||
|
|
366091fa87 | ||
|
|
c58b072c89 | ||
|
|
762c88adb8 | ||
|
|
af8ce568d1 | ||
|
|
b2c2934d05 | ||
|
|
cce26ec78e | ||
|
|
cb54602d49 | ||
|
|
9f740e5905 | ||
|
|
b23baf611a | ||
|
|
457f94ba26 | ||
|
|
fd612052f3 | ||
|
|
8858ec55c7 | ||
|
|
41efb8015d | ||
|
|
c93be1b2d5 | ||
|
|
680f8919ed | ||
|
|
c5812524f8 | ||
|
|
971303da8c | ||
|
|
50db77bf25 | ||
|
|
85d42c1993 | ||
|
|
2dfbb855d7 | ||
|
|
471f375a38 | ||
|
|
1d8c4d016f | ||
|
|
a5650b9439 | ||
|
|
904479ad43 | ||
|
|
86b666bba9 | ||
|
|
62f07c182c | ||
|
|
f405582f86 | ||
|
|
561cbbd144 | ||
|
|
84e2973aaa | ||
|
|
f49859ebfd | ||
|
|
bc59db5e6f | ||
|
|
dd928b4cbf | ||
|
|
3e0f7d0995 | ||
|
|
5ffe15d5ff | ||
|
|
516cbef2c4 | ||
|
|
9b6ffc201c | ||
|
|
ff8b8f0a8a | ||
|
|
0ca8d667d2 | ||
|
|
7112add67f | ||
|
|
761bc3ef85 | ||
|
|
1fb3011235 | ||
|
|
eb3e0c9c95 | ||
|
|
2250b7fbe3 | ||
|
|
c9f9feff1f | ||
|
|
d6b9c7e148 | ||
|
|
d10a1a7977 | ||
|
|
2bdb443255 | ||
|
|
4b2b21d247 | ||
|
|
8993ce5bf1 | ||
|
|
0f532a1174 | ||
|
|
f7ad363d86 | ||
|
|
9afea33403 | ||
|
|
d787b5d609 | ||
|
|
5dd0d1b7db | ||
|
|
07ac711b31 | ||
|
|
decfd858b8 | ||
|
|
076ed7770c | ||
|
|
a0be07c370 | ||
|
|
558c383088 | ||
|
|
1379735aff | ||
|
|
e3d86fee46 | ||
|
|
4cd8a56672 | ||
|
|
b2861f8948 | ||
|
|
98cc32703c | ||
|
|
fa06403000 | ||
|
|
e716c36b89 | ||
|
|
9fd2b5e3fa | ||
|
|
7e95010a29 | ||
|
|
3ebc5a6d3a | ||
|
|
fc98a79dbb | ||
|
|
fdc098267e | ||
|
|
a3dd84e854 | ||
|
|
a216b9e9ee | ||
|
|
8f386f6bb3 | ||
|
|
c07ac23532 | ||
|
|
f1d71da8a9 | ||
|
|
ef037457e5 | ||
|
|
76930250c0 | ||
|
|
1c246418f8 | ||
|
|
95a54a0f29 | ||
|
|
a4530243e1 | ||
|
|
09d00a6227 | ||
|
|
ba9b517427 | ||
|
|
6411bd79c6 | ||
|
|
810e58ea85 | ||
|
|
607d6c148a | ||
|
|
c9873e81b2 | ||
|
|
98d0706de8 | ||
|
|
fbe67c90c8 | ||
|
|
c67a488a09 | ||
|
|
8e93ce8929 | ||
|
|
c98ca7310f | ||
|
|
3b12276bc3 | ||
|
|
e6d348f382 | ||
|
|
df12fc2a86 | ||
|
|
39561751fc | ||
|
|
37d316aa09 | ||
|
|
dd43109596 | ||
|
|
823174f30a | ||
|
|
37c6952663 | ||
|
|
04c9b000ff | ||
|
|
ca3e71e214 | ||
|
|
d946d5a2bb | ||
|
|
8b1b9ac75a | ||
|
|
2f680ba990 | ||
|
|
a885db7d48 | ||
|
|
ee24101696 | ||
|
|
48fe54271a | ||
|
|
dff58c87f4 | ||
|
|
dde61aad32 | ||
|
|
0f6ef80ab2 | ||
|
|
e488861877 | ||
|
|
dffa1a5cba | ||
|
|
fe59d854d5 | ||
|
|
10731f3d6b | ||
|
|
89f7b72b6e | ||
|
|
85f2f87400 | ||
|
|
73ec940786 | ||
|
|
62be0392b6 | ||
|
|
24d31df55a | ||
|
|
841ef5d739 | ||
|
|
e582518bae | ||
|
|
8757bc471b | ||
|
|
ea9512977c | ||
|
|
9b798d228f | ||
|
|
804926fb5b | ||
|
|
118e9d29d5 | ||
|
|
c705953d77 | ||
|
|
852d1b9cad | ||
|
|
eedb3a1adc | ||
|
|
60dce66a4f | ||
|
|
9e19b29c31 | ||
|
|
2994250714 | ||
|
|
a6b0e9b856 | ||
|
|
3c2093119e | ||
|
|
5fe2eebceb | ||
|
|
4b1b92bb74 | ||
|
|
0fbb0d989e | ||
|
|
2dc94e6052 | ||
|
|
d9cb57a429 | ||
|
|
f7cfdd7cee | ||
|
|
b6d5d90d9d | ||
|
|
c7ab2baa6e | ||
|
|
0c45c5b7ea | ||
|
|
3dfb01d45b | ||
|
|
30e936837c | ||
|
|
311e2de4c1 | ||
|
|
c08fd6682f | ||
|
|
258bba0c2d | ||
|
|
372ca4f456 | ||
|
|
223d47af0e | ||
|
|
55cb683db4 | ||
|
|
ee8a33c568 | ||
|
|
61426d08de | ||
|
|
b630b63ef0 | ||
|
|
1d0c05d4f8 | ||
|
|
f07569df19 | ||
|
|
0120f31247 | ||
|
|
c2829ed98e | ||
|
|
221e66f46d | ||
|
|
738852e119 | ||
|
|
27b697b084 | ||
|
|
9e45373a74 | ||
|
|
eeb1025ac7 | ||
|
|
bc6f1e2469 | ||
|
|
bb48ae391e | ||
|
|
221011494d | ||
|
|
fb1239a2ad | ||
|
|
7de9477347 | ||
|
|
90957aeea4 | ||
|
|
47aae502a7 | ||
|
|
0bff98b5ec | ||
|
|
b52e40b80c | ||
|
|
4a00cd77bb | ||
|
|
e25e515f2e | ||
|
|
322ef9b967 | ||
|
|
d42ef5df02 | ||
|
|
f432f65bef | ||
|
|
1726b77ac5 | ||
|
|
620bec9cae | ||
|
|
7cd6e2e7fa | ||
|
|
7732836bd5 | ||
|
|
698edfda9d | ||
|
|
1c454b000f | ||
|
|
f42905b32e | ||
|
|
bdc822fad8 | ||
|
|
d3affb16bc | ||
|
|
2de3bf7f58 | ||
|
|
3cf4f38f5d | ||
|
|
4e0c10f488 | ||
|
|
3b06313243 | ||
|
|
6cd1c73efe | ||
|
|
063bbab6f5 | ||
|
|
aab4c494d6 | ||
|
|
bf46af2600 | ||
|
|
655763a9a7 | ||
|
|
a095ec2d8f | ||
|
|
12ab035aad | ||
|
|
99e4f7dd2c |
10
.github/workflows/gradle-wrapper-validation.yml
vendored
Normal file
10
.github/workflows/gradle-wrapper-validation.yml
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
name: "Validate Gradle Wrapper"
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
validation:
|
||||
name: "Validation"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: gradle/wrapper-validation-action@v1
|
||||
10
.gitignore
vendored
10
.gitignore
vendored
@@ -2,7 +2,8 @@
|
||||
|
||||
dependency-reduced-pom.xml
|
||||
doxygen.log
|
||||
buildcmake/
|
||||
build*/
|
||||
!buildSrc/
|
||||
|
||||
# Created by the jenkins test script
|
||||
test-reports
|
||||
@@ -214,3 +215,10 @@ ipch/
|
||||
|
||||
# Visual Studio 2015 cache/options directory
|
||||
.vs/
|
||||
|
||||
# compile_commands
|
||||
compile_commands.json
|
||||
|
||||
# clang configuration and clangd cache
|
||||
.clang
|
||||
.clangd/
|
||||
|
||||
11
.styleguide
11
.styleguide
@@ -9,16 +9,9 @@ cppSrcFileInclude {
|
||||
}
|
||||
|
||||
generatedFileExclude {
|
||||
gtest/
|
||||
ni-libraries/include/
|
||||
ni-libraries/lib/
|
||||
FRCNetComm\.java$
|
||||
simulation/frc_gazebo_plugins/frcgazebo/
|
||||
simulation/gz_msgs/src/include/simulation/gz_msgs/msgs\.h$
|
||||
}
|
||||
|
||||
modifiableFileExclude {
|
||||
\.so$
|
||||
simulation/halsim_gui/src/main/native/include/portable-file-dialogs\.h$
|
||||
}
|
||||
|
||||
repoRootNameOverride {
|
||||
@@ -29,11 +22,13 @@ includeOtherLibs {
|
||||
^cameraserver/
|
||||
^cscore
|
||||
^hal/
|
||||
^imgui
|
||||
^mockdata/
|
||||
^networktables/
|
||||
^ntcore
|
||||
^opencv2/
|
||||
^support/
|
||||
^units/
|
||||
^vision/
|
||||
^wpi/
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"enableCppIntellisense": true,
|
||||
"currentLanguage": "cpp",
|
||||
"projectYear": "2019",
|
||||
"teamNumber": 0
|
||||
}
|
||||
{
|
||||
"enableCppIntellisense": true,
|
||||
"currentLanguage": "cpp",
|
||||
"projectYear": "2020",
|
||||
"teamNumber": 0
|
||||
}
|
||||
|
||||
@@ -48,8 +48,14 @@ option(WITHOUT_JAVA "don't include java and JNI in the build" OFF)
|
||||
option(BUILD_SHARED_LIBS "build with shared libs (needed for JNI)" ON)
|
||||
option(WITHOUT_CSCORE "Don't build cscore (removes OpenCV requirement)" OFF)
|
||||
option(WITHOUT_ALLWPILIB "Don't build allwpilib (removes OpenCV requirement)" ON)
|
||||
option(WITH_TESTS "build unit tests (requires internet connection)" OFF)
|
||||
option(USE_EXTERNAL_HAL "Use a separately built HAL" OFF)
|
||||
set(EXTERNAL_HAL_FILE "" CACHE FILEPATH "Location to look for an external HAL CMake File")
|
||||
option(USE_VCPKG_LIBUV "Use vcpkg libuv" OFF)
|
||||
option(USE_VCPKG_EIGEN "Use vcpkg eigen" OFF)
|
||||
option(FLAT_INSTALL_WPILIB "Use a flat install directory" OFF)
|
||||
option(WITH_SIMULATION_MODULES "build simulation modules" OFF)
|
||||
set(OPENCV_JAVA_INSTALL_DIR "" CACHE PATH "Location to search for the OpenCV jar file")
|
||||
|
||||
if (NOT WITHOUT_JAVA AND NOT BUILD_SHARED_LIBS)
|
||||
message(FATAL_ERROR "
|
||||
@@ -59,34 +65,82 @@ FATAL: Cannot build static libs with Java enabled.
|
||||
")
|
||||
endif()
|
||||
|
||||
if (WITHOUT_JAVA OR WITHOUT_CSCORE)
|
||||
if(NOT "${OPENCV_JAVA_INSTALL_DIR}" STREQUAL "")
|
||||
message(WARNING "
|
||||
WARNING: OpenCV Java dir set but java is not enabled!
|
||||
It will be ignored.
|
||||
")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set( wpilib_dest wpilib)
|
||||
set( include_dest wpilib/include )
|
||||
set( main_lib_dest wpilib/lib )
|
||||
set( java_lib_dest wpilib/java )
|
||||
set( jni_lib_dest wpilib/jni )
|
||||
|
||||
if (MSVC)
|
||||
if (MSVC OR FLAT_INSTALL_WPILIB)
|
||||
set (wpilib_config_dir ${wpilib_dest})
|
||||
else()
|
||||
set (wpilib_config_dir share/wpilib)
|
||||
endif()
|
||||
|
||||
if (USE_VCPKG_LIBUV)
|
||||
set (LIBUV_VCPKG_REPLACE "find_package(unofficial-libuv CONFIG)")
|
||||
endif()
|
||||
|
||||
if (USE_VCPKG_EIGEN)
|
||||
set (EIGEN_VCPKG_REPLACE "find_package(Eigen3 CONFIG)")
|
||||
endif()
|
||||
|
||||
if (MSVC OR FLAT_INSTALL_WPILIB)
|
||||
set(WPIUTIL_DEP_REPLACE "include($\{SELF_DIR\}/wpiutil-config.cmake)")
|
||||
set(NTCORE_DEP_REPLACE "include($\{SELF_DIR\}/ntcore-config.cmake)")
|
||||
set(CSCORE_DEP_REPLACE_IMPL "include(\${SELF_DIR}/cscore-config.cmake)")
|
||||
set(CAMERASERVER_DEP_REPLACE_IMPL "include(\${SELF_DIR}/cameraserver-config.cmake)")
|
||||
set(HAL_DEP_REPLACE_IMPL "include(\${SELF_DIR}/hal-config.cmake)")
|
||||
set(WPILIBC_DEP_REPLACE_IMPL "include(\${SELF_DIR}/wpilibc-config.cmake)")
|
||||
else()
|
||||
set(WPIUTIL_DEP_REPLACE "find_dependency(wpiutil)")
|
||||
set(NTCORE_DEP_REPLACE "find_dependency(ntcore)")
|
||||
set(CSCORE_DEP_REPLACE_IMPL "find_dependency(cscore)")
|
||||
set(CAMERASERVER_DEP_REPLACE_IMPL "find_dependency(cameraserver)")
|
||||
set(HAL_DEP_REPLACE_IMPL "find_dependency(hal)")
|
||||
set(WPILIBC_DEP_REPLACE_IMPL "find_dependency(wpilibc)")
|
||||
endif()
|
||||
|
||||
set(FILENAME_DEP_REPLACE "get_filename_component(SELF_DIR \"$\{CMAKE_CURRENT_LIST_FILE\}\" PATH)")
|
||||
set(SELF_DIR "$\{SELF_DIR\}")
|
||||
|
||||
if (WITH_TESTS)
|
||||
enable_testing()
|
||||
add_subdirectory(googletest)
|
||||
include(GoogleTest)
|
||||
endif()
|
||||
|
||||
add_subdirectory(wpiutil)
|
||||
add_subdirectory(ntcore)
|
||||
|
||||
if (NOT WITHOUT_CSCORE)
|
||||
set(CSCORE_DEP_REPLACE ${CSCORE_DEP_REPLACE_IMPL})
|
||||
set(CAMERASERVER_DEP_REPLACE ${CAMERASERVER_DEP_REPLACE_IMPL})
|
||||
add_subdirectory(cscore)
|
||||
add_subdirectory(cameraserver)
|
||||
set (CSCORE_DEP_REPLACE "find_dependency(cscore)")
|
||||
set (CAMERASERVER_DEP_REPLACE "find_dependency(cameraserver)")
|
||||
if (NOT WITHOUT_ALLWPILIB)
|
||||
set(HAL_DEP_REPLACE ${HAL_DEP_REPLACE_IMPL})
|
||||
set(WPILIBC_DEP_REPLACE ${WPILIBC_DEP_REPLACE_IMPL})
|
||||
add_subdirectory(hal)
|
||||
add_subdirectory(wpilibj)
|
||||
add_subdirectory(wpilibc)
|
||||
set (HAL_DEP_REPLACE "find_dependency(hal)")
|
||||
set (WPILIBC_DEP_REPLACE "find_dependency(wpilibc)")
|
||||
add_subdirectory(myRobot)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (WITH_SIMULATION_MODULES AND NOT USE_EXTERNAL_HAL)
|
||||
add_subdirectory(imgui)
|
||||
add_subdirectory(simulation)
|
||||
endif()
|
||||
|
||||
configure_file(wpilib-config.cmake.in ${CMAKE_BINARY_DIR}/wpilib-config.cmake )
|
||||
install(FILES ${CMAKE_BINARY_DIR}/wpilib-config.cmake DESTINATION ${wpilib_config_dir})
|
||||
|
||||
@@ -20,7 +20,7 @@ So you want to contribute your changes back to WPILib. Great! We have a few cont
|
||||
- Substantial changes often need to have corresponding LabVIEW changes. To do this, we will work with NI on these large changes.
|
||||
- Changes should have tests.
|
||||
- Code should be well documented.
|
||||
- This often involves ScreenSteps. To add content to ScreenSteps, we will work with you to get the appropriate articles written.
|
||||
- This involves writing tutorials and/or usage guides for your submitted feature. These articles are then hosted on the [WPILib](https://docs.wpilib.org/) documentation website. See the [frc-docs repository](https://github.com/wpilibsuite/frc-docs) for more information.
|
||||
|
||||
## What to Contribute
|
||||
|
||||
@@ -37,7 +37,7 @@ So you want to contribute your changes back to WPILib. Great! We have a few cont
|
||||
|
||||
## Coding Guidelines
|
||||
|
||||
WPILib uses modified Google style guides for both C++ and Java, which can be found in the [styleguide repository](https://github.com/wpilibsuite/styleguide). Autoformatters are available for many popular editors at https://github.com/google/styleguide. Running wpiformat is required for all contributions and is enforced by our continuous integration system. We currently use clang-format 5.0 with wpiformat.
|
||||
WPILib uses modified Google style guides for both C++ and Java, which can be found in the [styleguide repository](https://github.com/wpilibsuite/styleguide). Autoformatters are available for many popular editors at https://github.com/google/styleguide. Running wpiformat is required for all contributions and is enforced by our continuous integration system. We currently use clang-format 6.0 with wpiformat.
|
||||
|
||||
While the library should be fully formatted according to the styles, additional elements of the style guide were not followed when the library was initially created. All new code should follow the guidelines. If you are looking for some easy ramp-up tasks, finding areas that don't follow the style guide and fixing them is very welcome.
|
||||
|
||||
@@ -53,4 +53,4 @@ When you first submit changes, Travis-CI will attempt to run `./gradlew check` o
|
||||
|
||||
## Licensing
|
||||
|
||||
By contributing to WPILib, you agree that your code will be distributed with WPILib, and licensed under the license for the WPILib project. You should not contribute code that you do not have permission to relicense in this manner. This includes code that is licensed under the GPL that you do not have permission to relicense, as WPILib is not released under a copyleft license. Our license is the 3-clause BSD license, which you can find [here](license.txt).
|
||||
By contributing to WPILib, you agree that your code will be distributed with WPILib, and licensed under the license for the WPILib project. You should not contribute code that you do not have permission to relicense in this manner. This includes code that is licensed under the GPL that you do not have permission to relicense, as WPILib is not released under a copyleft license. Our license is the 3-clause BSD license, which you can find [here](LICENSE.txt).
|
||||
|
||||
15
FasterBuilds.md
Normal file
15
FasterBuilds.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# Faster Builds for Developers
|
||||
|
||||
When you run `./gradlew build`, it builds EVERYTHING. This means debug and release builds for desktop and all installed cross compilers. For many developers, this is way too much, and causes much developer pain.
|
||||
|
||||
To help with some of these things, common tasks have shortcuts to only build necessary things for common development and testing tasks.
|
||||
|
||||
## Development (Desktop)
|
||||
|
||||
For projects `wpiutil`, `ntcore`, `cscore`, `hal` `wpilibOldCommands`, `wpilibNewCommands` and `cameraserver`, a `testDesktopJava` and a `testDesktopCpp` task exists. These can be ran with `./gradlew :projectName:task`, and will only build the minimum things required to run those tests.
|
||||
|
||||
For `wpilibc`, a `testDesktopCpp` task exists. For `wpilibj`, a `testDesktopJava` task exists.
|
||||
|
||||
For `wpilibcExamples`, a `buildDesktopCpp` task exists (These can't be ran, but they can compile).
|
||||
|
||||
For `wpilibjExamples`, a `buildDesktopJava` task exists.
|
||||
@@ -5,8 +5,8 @@ WPILib publishes its built artifacts to our Maven server for use by downstream p
|
||||
## Repositories
|
||||
We provide two repositories. These repositories are:
|
||||
|
||||
* (Release) http://first.wpi.edu/FRC/roborio/maven/release/
|
||||
* (Development) http://first.wpi.edu/FRC/roborio/maven/development/
|
||||
* (Release) https://frcmaven.wpi.edu/artifactory/release/
|
||||
* (Development) https://frcmaven.wpi.edu/artifactory/development/
|
||||
|
||||
The release repository is where official WPILib releases are pushed.
|
||||
The development repository is where development releases of every commit to [master](https://github.com/wpilibsuite/allwpilib/tree/master) is pushed.
|
||||
@@ -72,6 +72,10 @@ All artifacts are based at `edu.wpi.first.artifactname` in the repository.
|
||||
* hal
|
||||
* wpiutil
|
||||
|
||||
* halsim
|
||||
* imgui
|
||||
* wpiutil
|
||||
|
||||
* ntcore
|
||||
* wpiutil
|
||||
|
||||
@@ -85,7 +89,6 @@ All artifacts are based at `edu.wpi.first.artifactname` in the repository.
|
||||
* opencv
|
||||
* wpiutil
|
||||
|
||||
|
||||
* wpilibj
|
||||
* hal
|
||||
* cameraserver
|
||||
@@ -93,10 +96,35 @@ All artifacts are based at `edu.wpi.first.artifactname` in the repository.
|
||||
* cscore
|
||||
* wpiutil
|
||||
|
||||
|
||||
* wpilibc
|
||||
* hal
|
||||
* cameraserver
|
||||
* ntcore
|
||||
* cscore
|
||||
* wpiutil
|
||||
|
||||
* wpilibNewCommands
|
||||
* wpilibc
|
||||
* hal
|
||||
* cameraserver
|
||||
* ntcore
|
||||
* cscore
|
||||
* wpiutil
|
||||
|
||||
* wpilibNewCommands
|
||||
* wpilibc
|
||||
* hal
|
||||
* cameraserver
|
||||
* ntcore
|
||||
* cscore
|
||||
* wpiutil
|
||||
|
||||
### Third Party Artifacts
|
||||
|
||||
This repository provides the builds of the following third party software.
|
||||
|
||||
All artifacts are based at `edu.wpi.first.thirdparty.frcYEAR` in the repository.
|
||||
|
||||
* googletest
|
||||
* imgui
|
||||
* opencv
|
||||
|
||||
@@ -34,6 +34,8 @@ The following build options are available:
|
||||
* TODO
|
||||
* EXTERNAL_HAL_FILE
|
||||
* TODO
|
||||
* OPENCV_JAVA_INSTALL_DIR
|
||||
* Set this option to the location of the archive of the OpenCV Java bindings (it should be called opencv-xxx.jar, with the x'es being version numbers). NOTE: set it to the LOCATION of the file, not the file itself!
|
||||
|
||||
## Build Setup
|
||||
|
||||
|
||||
@@ -25,10 +25,10 @@ Using Gradle makes building WPILib very straightforward. It only has a few depen
|
||||
|
||||
- A C++ compiler
|
||||
- On Linux, GCC works fine
|
||||
- On Windows, you need Visual Studio 2017 (the free community edition works fine).
|
||||
- On Windows, you need Visual Studio 2019 (the free community edition works fine).
|
||||
Make sure to select the C++ Programming Language for installation
|
||||
- [ARM Compiler Toolchain](https://github.com/wpilibsuite/toolchain-builder/releases)
|
||||
* Note that for 2019 and beyond, you should use version 6 or greater of GCC
|
||||
- [ARM Compiler Toolchain](https://github.com/wpilibsuite/roborio-toolchain/releases)
|
||||
* Note that for 2020 and beyond, you should use version 7 or greater of GCC
|
||||
- Doxygen (Only required if you want to build the C++ documentation)
|
||||
|
||||
## Setup
|
||||
|
||||
@@ -31,13 +31,20 @@ sigslot wpiutil/src/main/native/include/wpi/Signal.h
|
||||
wpiutil/src/test/native/cpp/sigslot/
|
||||
tcpsockets wpiutil/src/main/native/cpp/TCP{Stream,Connector,Acceptor}.cpp
|
||||
wpiutil/src/main/native/include/wpi/TCP*.h
|
||||
Optional wpiutil/src/main/native/include/wpi/optional.h
|
||||
wpiutil/src/test/native/cpp/test_optional.cpp
|
||||
Bootstrap wpiutil/src/main/native/resources/bootstrap-*
|
||||
CoreUI wpiutil/src/main/native/resources/coreui-*
|
||||
Feather Icons wpiutil/src/main/native/resources/feather-*
|
||||
jQuery wpiutil/src/main/native/resources/jquery-*
|
||||
popper.js wpiutil/src/main/native/resources/popper-*
|
||||
units wpiutil/src/main/native/include/units/units.h
|
||||
Eigen wpiutil/src/main/native/eigeninclude/
|
||||
StackWalker wpiutil/src/main/native/windows/StackWalker.*
|
||||
Team 254 Library wpilibj/src/main/java/edu/wpi/first/wpilibj/spline/SplineParameterizer.java
|
||||
wpilibj/src/main/java/edu/wpi/first/wpilibj/trajectory/TrajectoryParameterizer.java
|
||||
wpilibc/src/main/native/include/spline/SplineParameterizer.h
|
||||
wpilibc/src/main/native/include/trajectory/TrajectoryParameterizer.h
|
||||
wpilibc/src/main/native/cpp/trajectory/TrajectoryParameterizer.cpp
|
||||
Portable File Dialogs simulation/halsim_gui/src/main/native/include/portable-file-dialogs.h
|
||||
|
||||
|
||||
==============================================================================
|
||||
@@ -221,36 +228,6 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
|
||||
==============================================================================
|
||||
Optional License
|
||||
==============================================================================
|
||||
Copyright (C) 2011 - 2017 Andrzej Krzemienski.
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
|
||||
==============================================================================
|
||||
Bootstrap License
|
||||
==============================================================================
|
||||
@@ -371,3 +348,462 @@ 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.
|
||||
|
||||
|
||||
=============
|
||||
units License
|
||||
=============
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Nic Holthaus
|
||||
|
||||
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.
|
||||
|
||||
|
||||
=============
|
||||
Eigen license
|
||||
=============
|
||||
Mozilla Public License Version 2.0
|
||||
==================================
|
||||
|
||||
1. Definitions
|
||||
--------------
|
||||
|
||||
1.1. "Contributor"
|
||||
means each individual or legal entity that creates, contributes to
|
||||
the creation of, or owns Covered Software.
|
||||
|
||||
1.2. "Contributor Version"
|
||||
means the combination of the Contributions of others (if any) used
|
||||
by a Contributor and that particular Contributor's Contribution.
|
||||
|
||||
1.3. "Contribution"
|
||||
means Covered Software of a particular Contributor.
|
||||
|
||||
1.4. "Covered Software"
|
||||
means Source Code Form to which the initial Contributor has attached
|
||||
the notice in Exhibit A, the Executable Form of such Source Code
|
||||
Form, and Modifications of such Source Code Form, in each case
|
||||
including portions thereof.
|
||||
|
||||
1.5. "Incompatible With Secondary Licenses"
|
||||
means
|
||||
|
||||
(a) that the initial Contributor has attached the notice described
|
||||
in Exhibit B to the Covered Software; or
|
||||
|
||||
(b) that the Covered Software was made available under the terms of
|
||||
version 1.1 or earlier of the License, but not also under the
|
||||
terms of a Secondary License.
|
||||
|
||||
1.6. "Executable Form"
|
||||
means any form of the work other than Source Code Form.
|
||||
|
||||
1.7. "Larger Work"
|
||||
means a work that combines Covered Software with other material, in
|
||||
a separate file or files, that is not Covered Software.
|
||||
|
||||
1.8. "License"
|
||||
means this document.
|
||||
|
||||
1.9. "Licensable"
|
||||
means having the right to grant, to the maximum extent possible,
|
||||
whether at the time of the initial grant or subsequently, any and
|
||||
all of the rights conveyed by this License.
|
||||
|
||||
1.10. "Modifications"
|
||||
means any of the following:
|
||||
|
||||
(a) any file in Source Code Form that results from an addition to,
|
||||
deletion from, or modification of the contents of Covered
|
||||
Software; or
|
||||
|
||||
(b) any new file in Source Code Form that contains any Covered
|
||||
Software.
|
||||
|
||||
1.11. "Patent Claims" of a Contributor
|
||||
means any patent claim(s), including without limitation, method,
|
||||
process, and apparatus claims, in any patent Licensable by such
|
||||
Contributor that would be infringed, but for the grant of the
|
||||
License, by the making, using, selling, offering for sale, having
|
||||
made, import, or transfer of either its Contributions or its
|
||||
Contributor Version.
|
||||
|
||||
1.12. "Secondary License"
|
||||
means either the GNU General Public License, Version 2.0, the GNU
|
||||
Lesser General Public License, Version 2.1, the GNU Affero General
|
||||
Public License, Version 3.0, or any later versions of those
|
||||
licenses.
|
||||
|
||||
1.13. "Source Code Form"
|
||||
means the form of the work preferred for making modifications.
|
||||
|
||||
1.14. "You" (or "Your")
|
||||
means an individual or a legal entity exercising rights under this
|
||||
License. For legal entities, "You" includes any entity that
|
||||
controls, is controlled by, or is under common control with You. For
|
||||
purposes of this definition, "control" means (a) the power, direct
|
||||
or indirect, to cause the direction or management of such entity,
|
||||
whether by contract or otherwise, or (b) ownership of more than
|
||||
fifty percent (50%) of the outstanding shares or beneficial
|
||||
ownership of such entity.
|
||||
|
||||
2. License Grants and Conditions
|
||||
--------------------------------
|
||||
|
||||
2.1. Grants
|
||||
|
||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
||||
non-exclusive license:
|
||||
|
||||
(a) under intellectual property rights (other than patent or trademark)
|
||||
Licensable by such Contributor to use, reproduce, make available,
|
||||
modify, display, perform, distribute, and otherwise exploit its
|
||||
Contributions, either on an unmodified basis, with Modifications, or
|
||||
as part of a Larger Work; and
|
||||
|
||||
(b) under Patent Claims of such Contributor to make, use, sell, offer
|
||||
for sale, have made, import, and otherwise transfer either its
|
||||
Contributions or its Contributor Version.
|
||||
|
||||
2.2. Effective Date
|
||||
|
||||
The licenses granted in Section 2.1 with respect to any Contribution
|
||||
become effective for each Contribution on the date the Contributor first
|
||||
distributes such Contribution.
|
||||
|
||||
2.3. Limitations on Grant Scope
|
||||
|
||||
The licenses granted in this Section 2 are the only rights granted under
|
||||
this License. No additional rights or licenses will be implied from the
|
||||
distribution or licensing of Covered Software under this License.
|
||||
Notwithstanding Section 2.1(b) above, no patent license is granted by a
|
||||
Contributor:
|
||||
|
||||
(a) for any code that a Contributor has removed from Covered Software;
|
||||
or
|
||||
|
||||
(b) for infringements caused by: (i) Your and any other third party's
|
||||
modifications of Covered Software, or (ii) the combination of its
|
||||
Contributions with other software (except as part of its Contributor
|
||||
Version); or
|
||||
|
||||
(c) under Patent Claims infringed by Covered Software in the absence of
|
||||
its Contributions.
|
||||
|
||||
This License does not grant any rights in the trademarks, service marks,
|
||||
or logos of any Contributor (except as may be necessary to comply with
|
||||
the notice requirements in Section 3.4).
|
||||
|
||||
2.4. Subsequent Licenses
|
||||
|
||||
No Contributor makes additional grants as a result of Your choice to
|
||||
distribute the Covered Software under a subsequent version of this
|
||||
License (see Section 10.2) or under the terms of a Secondary License (if
|
||||
permitted under the terms of Section 3.3).
|
||||
|
||||
2.5. Representation
|
||||
|
||||
Each Contributor represents that the Contributor believes its
|
||||
Contributions are its original creation(s) or it has sufficient rights
|
||||
to grant the rights to its Contributions conveyed by this License.
|
||||
|
||||
2.6. Fair Use
|
||||
|
||||
This License is not intended to limit any rights You have under
|
||||
applicable copyright doctrines of fair use, fair dealing, or other
|
||||
equivalents.
|
||||
|
||||
2.7. Conditions
|
||||
|
||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
|
||||
in Section 2.1.
|
||||
|
||||
3. Responsibilities
|
||||
-------------------
|
||||
|
||||
3.1. Distribution of Source Form
|
||||
|
||||
All distribution of Covered Software in Source Code Form, including any
|
||||
Modifications that You create or to which You contribute, must be under
|
||||
the terms of this License. You must inform recipients that the Source
|
||||
Code Form of the Covered Software is governed by the terms of this
|
||||
License, and how they can obtain a copy of this License. You may not
|
||||
attempt to alter or restrict the recipients' rights in the Source Code
|
||||
Form.
|
||||
|
||||
3.2. Distribution of Executable Form
|
||||
|
||||
If You distribute Covered Software in Executable Form then:
|
||||
|
||||
(a) such Covered Software must also be made available in Source Code
|
||||
Form, as described in Section 3.1, and You must inform recipients of
|
||||
the Executable Form how they can obtain a copy of such Source Code
|
||||
Form by reasonable means in a timely manner, at a charge no more
|
||||
than the cost of distribution to the recipient; and
|
||||
|
||||
(b) You may distribute such Executable Form under the terms of this
|
||||
License, or sublicense it under different terms, provided that the
|
||||
license for the Executable Form does not attempt to limit or alter
|
||||
the recipients' rights in the Source Code Form under this License.
|
||||
|
||||
3.3. Distribution of a Larger Work
|
||||
|
||||
You may create and distribute a Larger Work under terms of Your choice,
|
||||
provided that You also comply with the requirements of this License for
|
||||
the Covered Software. If the Larger Work is a combination of Covered
|
||||
Software with a work governed by one or more Secondary Licenses, and the
|
||||
Covered Software is not Incompatible With Secondary Licenses, this
|
||||
License permits You to additionally distribute such Covered Software
|
||||
under the terms of such Secondary License(s), so that the recipient of
|
||||
the Larger Work may, at their option, further distribute the Covered
|
||||
Software under the terms of either this License or such Secondary
|
||||
License(s).
|
||||
|
||||
3.4. Notices
|
||||
|
||||
You may not remove or alter the substance of any license notices
|
||||
(including copyright notices, patent notices, disclaimers of warranty,
|
||||
or limitations of liability) contained within the Source Code Form of
|
||||
the Covered Software, except that You may alter any license notices to
|
||||
the extent required to remedy known factual inaccuracies.
|
||||
|
||||
3.5. Application of Additional Terms
|
||||
|
||||
You may choose to offer, and to charge a fee for, warranty, support,
|
||||
indemnity or liability obligations to one or more recipients of Covered
|
||||
Software. However, You may do so only on Your own behalf, and not on
|
||||
behalf of any Contributor. You must make it absolutely clear that any
|
||||
such warranty, support, indemnity, or liability obligation is offered by
|
||||
You alone, and You hereby agree to indemnify every Contributor for any
|
||||
liability incurred by such Contributor as a result of warranty, support,
|
||||
indemnity or liability terms You offer. You may include additional
|
||||
disclaimers of warranty and limitations of liability specific to any
|
||||
jurisdiction.
|
||||
|
||||
4. Inability to Comply Due to Statute or Regulation
|
||||
---------------------------------------------------
|
||||
|
||||
If it is impossible for You to comply with any of the terms of this
|
||||
License with respect to some or all of the Covered Software due to
|
||||
statute, judicial order, or regulation then You must: (a) comply with
|
||||
the terms of this License to the maximum extent possible; and (b)
|
||||
describe the limitations and the code they affect. Such description must
|
||||
be placed in a text file included with all distributions of the Covered
|
||||
Software under this License. Except to the extent prohibited by statute
|
||||
or regulation, such description must be sufficiently detailed for a
|
||||
recipient of ordinary skill to be able to understand it.
|
||||
|
||||
5. Termination
|
||||
--------------
|
||||
|
||||
5.1. The rights granted under this License will terminate automatically
|
||||
if You fail to comply with any of its terms. However, if You become
|
||||
compliant, then the rights granted under this License from a particular
|
||||
Contributor are reinstated (a) provisionally, unless and until such
|
||||
Contributor explicitly and finally terminates Your grants, and (b) on an
|
||||
ongoing basis, if such Contributor fails to notify You of the
|
||||
non-compliance by some reasonable means prior to 60 days after You have
|
||||
come back into compliance. Moreover, Your grants from a particular
|
||||
Contributor are reinstated on an ongoing basis if such Contributor
|
||||
notifies You of the non-compliance by some reasonable means, this is the
|
||||
first time You have received notice of non-compliance with this License
|
||||
from such Contributor, and You become compliant prior to 30 days after
|
||||
Your receipt of the notice.
|
||||
|
||||
5.2. If You initiate litigation against any entity by asserting a patent
|
||||
infringement claim (excluding declaratory judgment actions,
|
||||
counter-claims, and cross-claims) alleging that a Contributor Version
|
||||
directly or indirectly infringes any patent, then the rights granted to
|
||||
You by any and all Contributors for the Covered Software under Section
|
||||
2.1 of this License shall terminate.
|
||||
|
||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
|
||||
end user license agreements (excluding distributors and resellers) which
|
||||
have been validly granted by You or Your distributors under this License
|
||||
prior to termination shall survive termination.
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 6. Disclaimer of Warranty *
|
||||
* ------------------------- *
|
||||
* *
|
||||
* Covered Software is provided under this License on an "as is" *
|
||||
* basis, without warranty of any kind, either expressed, implied, or *
|
||||
* statutory, including, without limitation, warranties that the *
|
||||
* Covered Software is free of defects, merchantable, fit for a *
|
||||
* particular purpose or non-infringing. The entire risk as to the *
|
||||
* quality and performance of the Covered Software is with You. *
|
||||
* Should any Covered Software prove defective in any respect, You *
|
||||
* (not any Contributor) assume the cost of any necessary servicing, *
|
||||
* repair, or correction. This disclaimer of warranty constitutes an *
|
||||
* essential part of this License. No use of any Covered Software is *
|
||||
* authorized under this License except under this disclaimer. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 7. Limitation of Liability *
|
||||
* -------------------------- *
|
||||
* *
|
||||
* Under no circumstances and under no legal theory, whether tort *
|
||||
* (including negligence), contract, or otherwise, shall any *
|
||||
* Contributor, or anyone who distributes Covered Software as *
|
||||
* permitted above, be liable to You for any direct, indirect, *
|
||||
* special, incidental, or consequential damages of any character *
|
||||
* including, without limitation, damages for lost profits, loss of *
|
||||
* goodwill, work stoppage, computer failure or malfunction, or any *
|
||||
* and all other commercial damages or losses, even if such party *
|
||||
* shall have been informed of the possibility of such damages. This *
|
||||
* limitation of liability shall not apply to liability for death or *
|
||||
* personal injury resulting from such party's negligence to the *
|
||||
* extent applicable law prohibits such limitation. Some *
|
||||
* jurisdictions do not allow the exclusion or limitation of *
|
||||
* incidental or consequential damages, so this exclusion and *
|
||||
* limitation may not apply to You. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
8. Litigation
|
||||
-------------
|
||||
|
||||
Any litigation relating to this License may be brought only in the
|
||||
courts of a jurisdiction where the defendant maintains its principal
|
||||
place of business and such litigation shall be governed by laws of that
|
||||
jurisdiction, without reference to its conflict-of-law provisions.
|
||||
Nothing in this Section shall prevent a party's ability to bring
|
||||
cross-claims or counter-claims.
|
||||
|
||||
9. Miscellaneous
|
||||
----------------
|
||||
|
||||
This License represents the complete agreement concerning the subject
|
||||
matter hereof. If any provision of this License is held to be
|
||||
unenforceable, such provision shall be reformed only to the extent
|
||||
necessary to make it enforceable. Any law or regulation which provides
|
||||
that the language of a contract shall be construed against the drafter
|
||||
shall not be used to construe this License against a Contributor.
|
||||
|
||||
10. Versions of the License
|
||||
---------------------------
|
||||
|
||||
10.1. New Versions
|
||||
|
||||
Mozilla Foundation is the license steward. Except as provided in Section
|
||||
10.3, no one other than the license steward has the right to modify or
|
||||
publish new versions of this License. Each version will be given a
|
||||
distinguishing version number.
|
||||
|
||||
10.2. Effect of New Versions
|
||||
|
||||
You may distribute the Covered Software under the terms of the version
|
||||
of the License under which You originally received the Covered Software,
|
||||
or under the terms of any subsequent version published by the license
|
||||
steward.
|
||||
|
||||
10.3. Modified Versions
|
||||
|
||||
If you create software not governed by this License, and you want to
|
||||
create a new license for such software, you may create and use a
|
||||
modified version of this License if you rename the license and remove
|
||||
any references to the name of the license steward (except to note that
|
||||
such modified license differs from this License).
|
||||
|
||||
10.4. Distributing Source Code Form that is Incompatible With Secondary
|
||||
Licenses
|
||||
|
||||
If You choose to distribute Source Code Form that is Incompatible With
|
||||
Secondary Licenses under the terms of this version of the License, the
|
||||
notice described in Exhibit B of this License must be attached.
|
||||
|
||||
Exhibit A - Source Code Form License Notice
|
||||
-------------------------------------------
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
If it is not possible or desirable to put the notice in a particular
|
||||
file, then You may include the notice in a location (such as a LICENSE
|
||||
file in a relevant directory) where a recipient would be likely to look
|
||||
for such a notice.
|
||||
|
||||
You may add additional accurate notices of copyright ownership.
|
||||
|
||||
Exhibit B - "Incompatible With Secondary Licenses" Notice
|
||||
---------------------------------------------------------
|
||||
|
||||
This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||
defined by the Mozilla Public License, v. 2.0.
|
||||
|
||||
|
||||
===================
|
||||
StackWalker License
|
||||
===================
|
||||
Copyright (c) 2005-2013, Jochen Kalmbach
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
Neither the name of Jochen Kalmbach nor the names of its contributors may be
|
||||
used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
================
|
||||
Team 254 Library
|
||||
================
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 Team 254
|
||||
|
||||
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.
|
||||
|
||||
91
azure-pipelines-testbench.yaml
Normal file
91
azure-pipelines-testbench.yaml
Normal file
@@ -0,0 +1,91 @@
|
||||
# Testing steps for real hardware
|
||||
|
||||
trigger:
|
||||
batch: true
|
||||
branches:
|
||||
include:
|
||||
- master
|
||||
|
||||
stages:
|
||||
- stage: Build
|
||||
jobs:
|
||||
- job: IntegrationTests
|
||||
displayName: Integration Tests
|
||||
pool:
|
||||
vmImage: 'Ubuntu 16.04'
|
||||
|
||||
container:
|
||||
image: wpilib/roborio-cross-ubuntu:2020-18.04
|
||||
|
||||
timeoutInMinutes: 0
|
||||
|
||||
steps:
|
||||
- task: Gradle@2
|
||||
condition: and(succeeded(), not(startsWith(variables['Build.SourceBranch'], 'refs/tags/v')))
|
||||
inputs:
|
||||
workingDirectory: ''
|
||||
gradleWrapperFile: 'gradlew'
|
||||
gradleOptions: '-Xmx3072m'
|
||||
publishJUnitResults: false
|
||||
testResultsFiles: '**/TEST-*.xml'
|
||||
tasks: 'copyWpilibJIntegrationTestJarToOutput copyWpilibCTestLibrariesToOutput'
|
||||
options: '-Ponlylinuxathena -PbuildServer'
|
||||
|
||||
- task: PublishPipelineArtifact@0
|
||||
inputs:
|
||||
artifactName: 'Integration Tests'
|
||||
targetPath: 'build/integrationTestFiles'
|
||||
|
||||
- stage: TestBench
|
||||
displayName: Test Bench
|
||||
jobs:
|
||||
- job: Cpp
|
||||
displayName: C++
|
||||
pool: RoboRioConnections
|
||||
timeoutInMinutes: 30
|
||||
workspace:
|
||||
clean: all
|
||||
steps:
|
||||
- task: DownloadPipelineArtifact@0
|
||||
inputs:
|
||||
artifactName: 'Integration Tests'
|
||||
targetPath: 'build/integrationTestFiles'
|
||||
|
||||
- task: ShellScript@2
|
||||
displayName: Run C++ Tests
|
||||
inputs:
|
||||
scriptPath: test-scripts/deploy-and-run-test-on-robot.sh
|
||||
args: 'cpp -A "--gtest_output=xml:/home/admin/testResults/cppreport.xml"'
|
||||
|
||||
- task: PublishTestResults@2
|
||||
displayName: Publish C++ Test Results
|
||||
inputs:
|
||||
testResultsFormat: 'JUnit'
|
||||
testResultsFiles: '*.xml'
|
||||
testRunTitle: 'C++ Test Report'
|
||||
searchFolder: '$(System.DefaultWorkingDirectory)/test-reports'
|
||||
|
||||
- job: Java
|
||||
pool: RoboRioConnections
|
||||
timeoutInMinutes: 30
|
||||
workspace:
|
||||
clean: all
|
||||
steps:
|
||||
- task: DownloadPipelineArtifact@0
|
||||
inputs:
|
||||
artifactName: 'Integration Tests'
|
||||
targetPath: 'build/integrationTestFiles'
|
||||
|
||||
- task: ShellScript@2
|
||||
displayName: Run Java Tests
|
||||
inputs:
|
||||
scriptPath: test-scripts/deploy-and-run-test-on-robot.sh
|
||||
args: 'java'
|
||||
|
||||
- task: PublishTestResults@2
|
||||
displayName: Publish Java Test Results
|
||||
inputs:
|
||||
testResultsFormat: 'JUnit'
|
||||
testResultsFiles: '*.xml'
|
||||
testRunTitle: 'Java Test Report'
|
||||
searchFolder: '$(System.DefaultWorkingDirectory)/test-reports'
|
||||
@@ -5,179 +5,413 @@
|
||||
|
||||
resources:
|
||||
containers:
|
||||
- container: wpilib2019
|
||||
image: wpilib/roborio-cross-ubuntu:2019-18.04
|
||||
- container: wpilib2020
|
||||
image: wpilib/roborio-cross-ubuntu:2020-18.04
|
||||
- container: raspbian
|
||||
image: wpilib/raspbian-cross-ubuntu:18.04
|
||||
image: wpilib/raspbian-cross-ubuntu:10-18.04
|
||||
- container: aarch64
|
||||
image: wpilib/aarch64-cross-ubuntu:bionic-18.04
|
||||
- container: ubuntu
|
||||
image: wpilib/ubuntu-base:18.04
|
||||
|
||||
jobs:
|
||||
- job: Linux_Arm
|
||||
pool:
|
||||
vmImage: 'Ubuntu 16.04'
|
||||
variables:
|
||||
- group: Artifactory-Package-Publish
|
||||
|
||||
container: wpilib2019
|
||||
trigger:
|
||||
batch: true
|
||||
branches:
|
||||
include:
|
||||
- master
|
||||
|
||||
steps:
|
||||
- task: Gradle@2
|
||||
inputs:
|
||||
workingDirectory: ''
|
||||
gradleWrapperFile: 'gradlew'
|
||||
gradleOptions: '-Xmx3072m'
|
||||
publishJUnitResults: false
|
||||
testResultsFiles: '**/TEST-*.xml'
|
||||
tasks: 'build'
|
||||
options: '-PonlyAthena'
|
||||
# checkStyleRunAnalysis: true
|
||||
# pmdRunAnalysis: true
|
||||
stages:
|
||||
- stage: Build
|
||||
jobs:
|
||||
- job: Linux_Arm
|
||||
pool:
|
||||
vmImage: 'Ubuntu 16.04'
|
||||
|
||||
- job: Linux_Raspbian
|
||||
pool:
|
||||
vmImage: 'Ubuntu 16.04'
|
||||
container: wpilib2020
|
||||
|
||||
container: raspbian
|
||||
timeoutInMinutes: 0
|
||||
|
||||
steps:
|
||||
- task: Gradle@2
|
||||
inputs:
|
||||
workingDirectory: ''
|
||||
gradleWrapperFile: 'gradlew'
|
||||
gradleOptions: '-Xmx3072m'
|
||||
publishJUnitResults: true
|
||||
testResultsFiles: '**/TEST-*.xml'
|
||||
tasks: 'build'
|
||||
options: '-PonlyRaspbian'
|
||||
# checkStyleRunAnalysis: true
|
||||
# pmdRunAnalysis: true
|
||||
|
||||
- job: Linux
|
||||
pool:
|
||||
vmImage: 'Ubuntu 16.04'
|
||||
|
||||
container: wpilib2019
|
||||
|
||||
steps:
|
||||
- task: Gradle@2
|
||||
inputs:
|
||||
workingDirectory: ''
|
||||
gradleWrapperFile: 'gradlew'
|
||||
gradleOptions: '-Xmx3072m'
|
||||
publishJUnitResults: true
|
||||
testResultsFiles: '**/TEST-*.xml'
|
||||
tasks: 'build'
|
||||
options: '-PskipAthena'
|
||||
# checkStyleRunAnalysis: true
|
||||
# pmdRunAnalysis: true
|
||||
|
||||
- job: Styleguide
|
||||
pool:
|
||||
vmImage: 'Ubuntu 16.04'
|
||||
|
||||
steps:
|
||||
- script: |
|
||||
sudo apt-get update -y
|
||||
sudo apt-get install clang-format-5.0 python3-setuptools -y
|
||||
sudo pip3 install --upgrade pip
|
||||
sudo pip3 install wpiformat
|
||||
git checkout -b master
|
||||
displayName: 'Install Dependencies'
|
||||
- script: |
|
||||
wpiformat -y 2018 -clang 5.0
|
||||
displayName: 'Run WPIFormat'
|
||||
failOnStderr: true
|
||||
- script: |
|
||||
git --no-pager diff --exit-code HEAD # Ensure formatter made no changes
|
||||
displayName: 'Check WPIFormat Output'
|
||||
failOnStderr: true
|
||||
|
||||
- job: CMakeBuild
|
||||
pool:
|
||||
vmImage: 'Ubuntu 16.04'
|
||||
|
||||
container: wpilib2019
|
||||
|
||||
steps:
|
||||
- task: CMake@1
|
||||
steps:
|
||||
- task: Gradle@2
|
||||
condition: and(succeeded(), not(startsWith(variables['Build.SourceBranch'], 'refs/tags/v')))
|
||||
inputs:
|
||||
cmakeArgs: '-DWITHOUT_ALLWPILIB=OFF ..'
|
||||
workingDirectory: ''
|
||||
gradleWrapperFile: 'gradlew'
|
||||
gradleOptions: '-Xmx3072m'
|
||||
publishJUnitResults: false
|
||||
testResultsFiles: '**/TEST-*.xml'
|
||||
tasks: 'build'
|
||||
options: '-Ponlylinuxathena -PbuildServer'
|
||||
|
||||
- task: Gradle@2
|
||||
condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/v'))
|
||||
inputs:
|
||||
workingDirectory: ''
|
||||
gradleWrapperFile: 'gradlew'
|
||||
gradleOptions: '-Xmx3072m'
|
||||
publishJUnitResults: false
|
||||
testResultsFiles: '**/TEST-*.xml'
|
||||
tasks: 'build'
|
||||
options: '-Ponlylinuxathena -PreleaseMode -PbuildServer'
|
||||
|
||||
- task: PublishPipelineArtifact@0
|
||||
inputs:
|
||||
artifactName: 'Athena'
|
||||
targetPath: 'build/allOutputs'
|
||||
|
||||
- job: Linux_Raspbian
|
||||
pool:
|
||||
vmImage: 'Ubuntu 16.04'
|
||||
|
||||
container: raspbian
|
||||
|
||||
timeoutInMinutes: 0
|
||||
|
||||
steps:
|
||||
- task: Gradle@2
|
||||
condition: and(succeeded(), not(startsWith(variables['Build.SourceBranch'], 'refs/tags/v')))
|
||||
inputs:
|
||||
workingDirectory: ''
|
||||
gradleWrapperFile: 'gradlew'
|
||||
gradleOptions: '-Xmx3072m'
|
||||
publishJUnitResults: true
|
||||
testResultsFiles: '**/TEST-*.xml'
|
||||
tasks: 'build'
|
||||
options: '-Ponlylinuxraspbian -PbuildServer'
|
||||
|
||||
- task: Gradle@2
|
||||
condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/v'))
|
||||
inputs:
|
||||
workingDirectory: ''
|
||||
gradleWrapperFile: 'gradlew'
|
||||
gradleOptions: '-Xmx3072m'
|
||||
publishJUnitResults: true
|
||||
testResultsFiles: '**/TEST-*.xml'
|
||||
tasks: 'build'
|
||||
options: '-Ponlylinuxraspbian -PreleaseMode -PbuildServer'
|
||||
|
||||
- task: PublishPipelineArtifact@0
|
||||
inputs:
|
||||
artifactName: 'Raspbian'
|
||||
targetPath: 'build/allOutputs'
|
||||
|
||||
- job: Linux_Aarch64
|
||||
pool:
|
||||
vmImage: 'Ubuntu 16.04'
|
||||
|
||||
container: aarch64
|
||||
|
||||
timeoutInMinutes: 0
|
||||
|
||||
steps:
|
||||
- task: Gradle@2
|
||||
condition: and(succeeded(), not(startsWith(variables['Build.SourceBranch'], 'refs/tags/v')))
|
||||
inputs:
|
||||
workingDirectory: ''
|
||||
gradleWrapperFile: 'gradlew'
|
||||
gradleOptions: '-Xmx3072m'
|
||||
publishJUnitResults: true
|
||||
testResultsFiles: '**/TEST-*.xml'
|
||||
tasks: 'build'
|
||||
options: '-Ponlylinuxaarch64bionic -PbuildServer'
|
||||
|
||||
- task: Gradle@2
|
||||
condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/v'))
|
||||
inputs:
|
||||
workingDirectory: ''
|
||||
gradleWrapperFile: 'gradlew'
|
||||
gradleOptions: '-Xmx3072m'
|
||||
publishJUnitResults: true
|
||||
testResultsFiles: '**/TEST-*.xml'
|
||||
tasks: 'build'
|
||||
options: '-Ponlylinuxaarch64bionic -PreleaseMode -PbuildServer'
|
||||
|
||||
- task: PublishPipelineArtifact@0
|
||||
inputs:
|
||||
artifactName: 'Aarch64'
|
||||
targetPath: 'build/allOutputs'
|
||||
|
||||
- job: Linux
|
||||
pool:
|
||||
vmImage: 'Ubuntu 16.04'
|
||||
|
||||
container: ubuntu
|
||||
|
||||
timeoutInMinutes: 0
|
||||
|
||||
steps:
|
||||
- task: Gradle@2
|
||||
condition: and(succeeded(), not(startsWith(variables['Build.SourceBranch'], 'refs/tags/v')))
|
||||
inputs:
|
||||
workingDirectory: ''
|
||||
gradleWrapperFile: 'gradlew'
|
||||
gradleOptions: '-Xmx3072m'
|
||||
publishJUnitResults: true
|
||||
testResultsFiles: '**/TEST-*.xml'
|
||||
tasks: 'build'
|
||||
options: '-PbuildServer'
|
||||
|
||||
- task: Gradle@2
|
||||
condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/v'))
|
||||
inputs:
|
||||
workingDirectory: ''
|
||||
gradleWrapperFile: 'gradlew'
|
||||
gradleOptions: '-Xmx3072m'
|
||||
publishJUnitResults: true
|
||||
testResultsFiles: '**/TEST-*.xml'
|
||||
tasks: 'build'
|
||||
options: '-PreleaseMode -PbuildServer'
|
||||
|
||||
- task: PublishPipelineArtifact@0
|
||||
inputs:
|
||||
artifactName: 'Linux'
|
||||
targetPath: 'build/allOutputs'
|
||||
|
||||
- job: Styleguide
|
||||
pool:
|
||||
vmImage: 'Ubuntu 16.04'
|
||||
|
||||
container: ubuntu
|
||||
|
||||
timeoutInMinutes: 0
|
||||
|
||||
steps:
|
||||
- script: |
|
||||
sudo pip3 install wpiformat
|
||||
displayName: 'Install wpiformat'
|
||||
- script: |
|
||||
git checkout -b master
|
||||
wpiformat -clang 6.0
|
||||
displayName: 'Run wpiformat'
|
||||
- script: |
|
||||
# Ensure formatter made no changes
|
||||
git --no-pager diff --exit-code HEAD
|
||||
displayName: 'Check wpiformat Output'
|
||||
|
||||
- job: CMakeBuild
|
||||
pool:
|
||||
vmImage: 'Ubuntu 16.04'
|
||||
|
||||
container: wpilib2020
|
||||
|
||||
timeoutInMinutes: 0
|
||||
|
||||
steps:
|
||||
- task: CMake@1
|
||||
inputs:
|
||||
cmakeArgs: '-DWITHOUT_ALLWPILIB=OFF ..'
|
||||
- script: |
|
||||
make -j3
|
||||
workingDirectory: 'build'
|
||||
displayName: 'Build'
|
||||
|
||||
- job: Windows_64_Bit
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
|
||||
timeoutInMinutes: 0
|
||||
steps:
|
||||
- task: Gradle@2
|
||||
condition: and(succeeded(), not(startsWith(variables['Build.SourceBranch'], 'refs/tags/v')))
|
||||
inputs:
|
||||
workingDirectory: ''
|
||||
gradleWrapperFile: 'gradlew'
|
||||
gradleOptions: '-Xmx3072m'
|
||||
jdkVersionOption: '1.11'
|
||||
publishJUnitResults: true
|
||||
testResultsFiles: '**/TEST-*.xml'
|
||||
tasks: 'build'
|
||||
options: '-PskipPMD -PbuildServer'
|
||||
|
||||
- task: Gradle@2
|
||||
condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/v'))
|
||||
inputs:
|
||||
workingDirectory: ''
|
||||
gradleWrapperFile: 'gradlew'
|
||||
gradleOptions: '-Xmx3072m'
|
||||
jdkVersionOption: '1.11'
|
||||
publishJUnitResults: true
|
||||
testResultsFiles: '**/TEST-*.xml'
|
||||
tasks: 'build'
|
||||
options: '-PskipPMD -PreleaseMode -PbuildServer'
|
||||
|
||||
- task: PublishPipelineArtifact@0
|
||||
inputs:
|
||||
artifactName: 'Win64'
|
||||
targetPath: 'build/allOutputs'
|
||||
|
||||
- job: Windows_32_Bit
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
|
||||
timeoutInMinutes: 0
|
||||
steps:
|
||||
- powershell: |
|
||||
mkdir build
|
||||
$ProgressPreference = 'SilentlyContinue'
|
||||
wget "https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11.0.4%2B11/OpenJDK11U-jdk_x86-32_windows_hotspot_11.0.4_11.zip" -O "build\jdk.zip"
|
||||
displayName: 'Download JDK'
|
||||
- task: JavaToolInstaller@0
|
||||
inputs:
|
||||
jdkSourceOption: localDirectory
|
||||
jdkFile: 'build/jdk.zip'
|
||||
jdkDestinationDirectory: 'build/jdkinst'
|
||||
jdkArchitectureOption: x86
|
||||
|
||||
- task: Gradle@2
|
||||
condition: and(succeeded(), not(startsWith(variables['Build.SourceBranch'], 'refs/tags/v')))
|
||||
inputs:
|
||||
workingDirectory: ''
|
||||
gradleWrapperFile: 'gradlew'
|
||||
gradleOptions: '-Xmx1024m'
|
||||
publishJUnitResults: true
|
||||
testResultsFiles: '**/TEST-*.xml'
|
||||
tasks: 'build'
|
||||
options: '-PskipPMD -PbuildServer'
|
||||
|
||||
- task: Gradle@2
|
||||
condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/v'))
|
||||
inputs:
|
||||
workingDirectory: ''
|
||||
gradleWrapperFile: 'gradlew'
|
||||
gradleOptions: '-Xmx1024m'
|
||||
publishJUnitResults: true
|
||||
testResultsFiles: '**/TEST-*.xml'
|
||||
tasks: 'build'
|
||||
options: '-PskipPMD -PreleaseMode -PbuildServer'
|
||||
|
||||
- task: PublishPipelineArtifact@0
|
||||
inputs:
|
||||
artifactName: 'Win32'
|
||||
targetPath: 'build/allOutputs'
|
||||
|
||||
- job: Mac
|
||||
pool:
|
||||
vmImage: 'macOS-10.14'
|
||||
|
||||
timeoutInMinutes: 0
|
||||
steps:
|
||||
- script: |
|
||||
make -j3
|
||||
workingDirectory: 'build'
|
||||
displayName: 'Build'
|
||||
mkdir build
|
||||
export JAVA_HOME=`/usr/libexec/java_home -v 11`
|
||||
displayName: 'Setup JDK'
|
||||
|
||||
- job: Windows_64_Bit
|
||||
pool:
|
||||
vmImage: 'vs2017-win2016'
|
||||
steps:
|
||||
- powershell: |
|
||||
mkdir build
|
||||
$ProgressPreference = 'SilentlyContinue'
|
||||
wget "https://download.java.net/java/ga/jdk11/openjdk-11_windows-x64_bin.zip" -O "build\jdk.zip"
|
||||
displayName: 'Download JDK'
|
||||
- task: JavaToolInstaller@0
|
||||
inputs:
|
||||
jdkSourceOption: localDirectory
|
||||
jdkFile: 'build/jdk.zip'
|
||||
jdkDestinationDirectory: 'build/jdkinst'
|
||||
jdkArchitectureOption: x64
|
||||
- task: Gradle@2
|
||||
inputs:
|
||||
workingDirectory: ''
|
||||
gradleWrapperFile: 'gradlew'
|
||||
gradleOptions: '-Xmx3072m'
|
||||
publishJUnitResults: true
|
||||
testResultsFiles: '**/TEST-*.xml'
|
||||
tasks: 'build'
|
||||
# checkStyleRunAnalysis: true
|
||||
# pmdRunAnalysis: true
|
||||
- task: Gradle@2
|
||||
condition: and(succeeded(), not(startsWith(variables['Build.SourceBranch'], 'refs/tags/v')))
|
||||
inputs:
|
||||
workingDirectory: ''
|
||||
gradleWrapperFile: 'gradlew'
|
||||
gradleOptions: '-Xmx3072m'
|
||||
jdkVersionOption: '1.11'
|
||||
publishJUnitResults: true
|
||||
testResultsFiles: '**/TEST-*.xml'
|
||||
tasks: 'build'
|
||||
options: '-PbuildServer'
|
||||
|
||||
- job: Windows_32_Bit
|
||||
pool:
|
||||
vmImage: 'vs2017-win2016'
|
||||
steps:
|
||||
- powershell: |
|
||||
mkdir build
|
||||
$ProgressPreference = 'SilentlyContinue'
|
||||
wget "https://github.com/wpilibsuite/frc-openjdk-windows/releases/download/v11.0.0u28-1/jdk-x86-11.0.0u28-1.zip" -O "build\jdk.zip"
|
||||
displayName: 'Download JDK'
|
||||
- task: JavaToolInstaller@0
|
||||
inputs:
|
||||
jdkSourceOption: localDirectory
|
||||
jdkFile: 'build/jdk.zip'
|
||||
jdkDestinationDirectory: 'build/jdkinst'
|
||||
jdkArchitectureOption: x86
|
||||
- task: Gradle@2
|
||||
inputs:
|
||||
workingDirectory: ''
|
||||
gradleWrapperFile: 'gradlew'
|
||||
gradleOptions: '-Xmx1024m'
|
||||
publishJUnitResults: true
|
||||
testResultsFiles: '**/TEST-*.xml'
|
||||
tasks: 'build'
|
||||
# checkStyleRunAnalysis: true
|
||||
# pmdRunAnalysis: true
|
||||
- task: Gradle@2
|
||||
condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/v'))
|
||||
inputs:
|
||||
workingDirectory: ''
|
||||
gradleWrapperFile: 'gradlew'
|
||||
gradleOptions: '-Xmx3072m'
|
||||
jdkVersionOption: '1.11'
|
||||
publishJUnitResults: true
|
||||
testResultsFiles: '**/TEST-*.xml'
|
||||
tasks: 'build'
|
||||
options: '-PreleaseMode -PbuildServer'
|
||||
|
||||
- job: Mac
|
||||
pool:
|
||||
vmImage: 'xcode9-macos10.13'
|
||||
steps:
|
||||
- task: PublishPipelineArtifact@0
|
||||
inputs:
|
||||
artifactName: 'Mac'
|
||||
targetPath: 'build/allOutputs'
|
||||
|
||||
- stage: Combine
|
||||
jobs:
|
||||
- job: CombineJob
|
||||
pool:
|
||||
vmImage: 'macOS-10.14'
|
||||
|
||||
timeoutInMinutes: 0
|
||||
|
||||
steps:
|
||||
- checkout: none
|
||||
- script: |
|
||||
mkdir build
|
||||
wget "https://download.java.net/java/ga/jdk11/openjdk-11_osx-x64_bin.tar.gz" -O "build/jdk.tar.gz"
|
||||
sudo tar xvzf build/jdk.tar.gz -C /Library/Java/JavaVirtualMachines/
|
||||
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-11.jdk/Contents/Home/
|
||||
displayName: 'Setup JDK'
|
||||
- script: |
|
||||
rm /Users/vsts/.gradle/init.d/log-gradle-version-plugin.gradle
|
||||
displayName: 'Delete Version init script'
|
||||
git clone https://github.com/wpilibsuite/build-tools
|
||||
displayName: 'Clone Combiner'
|
||||
- task: DownloadPipelineArtifact@0
|
||||
inputs:
|
||||
artifactName: 'Mac'
|
||||
targetPath: 'build-tools/combiner/products/build/allOutputs'
|
||||
- task: DownloadPipelineArtifact@0
|
||||
inputs:
|
||||
artifactName: 'Win32'
|
||||
targetPath: 'build-tools/combiner/products/build/allOutputs'
|
||||
- task: DownloadPipelineArtifact@0
|
||||
inputs:
|
||||
artifactName: 'Win64'
|
||||
targetPath: 'build-tools/combiner/products/build/allOutputs'
|
||||
- task: DownloadPipelineArtifact@0
|
||||
inputs:
|
||||
artifactName: 'Linux'
|
||||
targetPath: 'build-tools/combiner/products/build/allOutputs'
|
||||
- task: DownloadPipelineArtifact@0
|
||||
inputs:
|
||||
artifactName: 'Raspbian'
|
||||
targetPath: 'build-tools/combiner/products/build/allOutputs'
|
||||
- task: DownloadPipelineArtifact@0
|
||||
inputs:
|
||||
artifactName: 'Athena'
|
||||
targetPath: 'build-tools/combiner/products/build/allOutputs'
|
||||
- task: DownloadPipelineArtifact@0
|
||||
inputs:
|
||||
artifactName: 'Aarch64'
|
||||
targetPath: 'build-tools/combiner/products/build/allOutputs'
|
||||
|
||||
# PR Builds
|
||||
- task: Gradle@2
|
||||
inputs:
|
||||
workingDirectory: ''
|
||||
gradleWrapperFile: 'gradlew'
|
||||
workingDirectory: 'build-tools/combiner'
|
||||
gradleWrapperFile: 'build-tools/combiner/gradlew'
|
||||
gradleOptions: '-Xmx3072m'
|
||||
javaHomeOption: 'path'
|
||||
jdkDirectory: '/Library/Java/JavaVirtualMachines/jdk-11.jdk/Contents/Home/'
|
||||
publishJUnitResults: true
|
||||
testResultsFiles: '**/TEST-*.xml'
|
||||
tasks: 'build'
|
||||
# checkStyleRunAnalysis: true
|
||||
# pmdRunAnalysis: true
|
||||
tasks: 'publish '
|
||||
options: '-Pallwpilib'
|
||||
condition: and(succeeded(), and(ne(variables['Build.SourceBranch'], 'refs/heads/master'), not(startsWith(variables['Build.SourceBranch'], 'refs/tags/v'))))
|
||||
|
||||
# Master Builds
|
||||
- task: Gradle@2
|
||||
inputs:
|
||||
workingDirectory: 'build-tools/combiner'
|
||||
gradleWrapperFile: 'build-tools/combiner/gradlew'
|
||||
gradleOptions: '-Xmx3072m'
|
||||
tasks: 'publish '
|
||||
options: '-Pallwpilib'
|
||||
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master'))
|
||||
env:
|
||||
RUN_AZURE_ARTIFACTORY_RELEASE: 'TRUE'
|
||||
ARTIFACTORY_PUBLISH_USERNAME: $(PublishUserName)
|
||||
ARTIFACTORY_PUBLISH_PASSWORD: $(PublishPassword)
|
||||
|
||||
# Tagged Builds
|
||||
- task: Gradle@2
|
||||
inputs:
|
||||
workingDirectory: 'build-tools/combiner'
|
||||
gradleWrapperFile: 'build-tools/combiner/gradlew'
|
||||
gradleOptions: '-Xmx3072m'
|
||||
tasks: 'publish '
|
||||
options: '-Pallwpilib -PreleaseRepoPublish'
|
||||
condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/v'))
|
||||
env:
|
||||
RUN_AZURE_ARTIFACTORY_RELEASE: 'TRUE'
|
||||
ARTIFACTORY_PUBLISH_USERNAME: $(PublishUserName)
|
||||
ARTIFACTORY_PUBLISH_PASSWORD: $(PublishPassword)
|
||||
|
||||
- script: |
|
||||
echo "##vso[task.setvariable variable=UserHome]$HOME"
|
||||
displayName: 'Set Home Variable'
|
||||
- task: PublishPipelineArtifact@0
|
||||
inputs:
|
||||
artifactName: 'Maven'
|
||||
targetPath: $(UserHome)/releases
|
||||
|
||||
68
build.gradle
68
build.gradle
@@ -1,18 +1,35 @@
|
||||
import edu.wpi.first.toolchain.*
|
||||
|
||||
plugins {
|
||||
id 'base'
|
||||
id 'edu.wpi.first.wpilib.versioning.WPILibVersioningPlugin' version '2.3'
|
||||
id 'edu.wpi.first.NativeUtils' version '2.1.2'
|
||||
id 'edu.wpi.first.GradleJni' version '0.3.1'
|
||||
id 'edu.wpi.first.GradleVsCode' version '0.7.1'
|
||||
id 'edu.wpi.first.wpilib.versioning.WPILibVersioningPlugin' version '4.0.1'
|
||||
id 'edu.wpi.first.wpilib.repositories.WPILibRepositoriesPlugin' version '2020.2'
|
||||
id 'edu.wpi.first.NativeUtils' apply false
|
||||
id 'edu.wpi.first.GradleJni' version '0.10.1'
|
||||
id 'edu.wpi.first.GradleVsCode' version '0.11.0'
|
||||
id 'idea'
|
||||
id 'visual-studio'
|
||||
id 'com.gradle.build-scan' version '2.0.2'
|
||||
id 'net.ltgt.errorprone' version '0.6' apply false
|
||||
id 'com.github.johnrengelman.shadow' version '4.0.3' apply false
|
||||
id 'net.ltgt.errorprone' version '1.1.1' apply false
|
||||
id 'com.github.johnrengelman.shadow' version '5.2.0' apply false
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
if (project.hasProperty('buildServer')) {
|
||||
wpilibVersioning.buildServerMode = true
|
||||
}
|
||||
|
||||
if (project.hasProperty('releaseMode')) {
|
||||
wpilibVersioning.releaseMode = true
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
if (project.hasProperty('releaseMode')) {
|
||||
wpilibRepositories.addAllReleaseRepositories(it)
|
||||
} else {
|
||||
wpilibRepositories.addAllDevelopmentRepositories(it)
|
||||
}
|
||||
}
|
||||
|
||||
buildScan {
|
||||
@@ -24,20 +41,11 @@ buildScan {
|
||||
|
||||
ext.licenseFile = files("$rootDir/LICENSE.txt", "$rootDir/ThirdPartyNotices.txt")
|
||||
|
||||
// Ensure that the WPILibVersioningPlugin is setup by setting the release type, if releaseType wasn't
|
||||
// already specified on the command line
|
||||
if (!hasProperty('releaseType')) {
|
||||
WPILibVersion {
|
||||
releaseType = 'dev'
|
||||
}
|
||||
if (project.hasProperty("publishVersion")) {
|
||||
wpilibVersioning.version.set(project.publishVersion)
|
||||
}
|
||||
|
||||
def pubVersion
|
||||
if (project.hasProperty("publishVersion")) {
|
||||
pubVersion = project.publishVersion
|
||||
} else {
|
||||
pubVersion = WPILibVersion.version
|
||||
}
|
||||
wpilibVersioning.version.finalizeValue()
|
||||
|
||||
def outputsFolder = file("$buildDir/allOutputs")
|
||||
|
||||
@@ -54,7 +62,7 @@ task outputVersions() {
|
||||
}
|
||||
|
||||
doLast {
|
||||
versionFile.write pubVersion
|
||||
versionFile.write wpilibVersioning.version.get()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,18 +95,20 @@ subprojects {
|
||||
|
||||
apply from: "${rootDir}/shared/java/javastyle.gradle"
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
// Disables doclint in java 8.
|
||||
if (JavaVersion.current().isJava8Compatible()) {
|
||||
tasks.withType(Javadoc) {
|
||||
options.addStringOption('Xdoclint:none', '-quiet')
|
||||
if (project.name != "docs") {
|
||||
options.addStringOption('Xdoclint:none', '-quiet')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wrapper {
|
||||
gradleVersion = '5.0'
|
||||
ext.getCurrentArch = {
|
||||
return NativePlatforms.desktop
|
||||
}
|
||||
|
||||
wrapper {
|
||||
gradleVersion = '6.0'
|
||||
}
|
||||
|
||||
9
buildSrc/build.gradle
Normal file
9
buildSrc/build.gradle
Normal file
@@ -0,0 +1,9 @@
|
||||
repositories {
|
||||
maven {
|
||||
url "https://plugins.gradle.org/m2/"
|
||||
mavenLocal()
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
implementation "edu.wpi.first:native-utils:2020.7.2"
|
||||
}
|
||||
70
buildSrc/src/main/groovy/DisableBuildingGTest.groovy
Normal file
70
buildSrc/src/main/groovy/DisableBuildingGTest.groovy
Normal file
@@ -0,0 +1,70 @@
|
||||
|
||||
import org.gradle.api.GradleException;
|
||||
import org.gradle.api.Plugin;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.Task;
|
||||
import org.gradle.api.file.FileTree;
|
||||
import org.gradle.api.tasks.compile.JavaCompile;
|
||||
import org.gradle.language.base.internal.ProjectLayout;
|
||||
import org.gradle.language.base.plugins.ComponentModelBasePlugin;
|
||||
import org.gradle.language.nativeplatform.tasks.AbstractNativeSourceCompileTask;
|
||||
import org.gradle.model.ModelMap;
|
||||
import edu.wpi.first.toolchain.ToolchainExtension
|
||||
import org.gradle.model.Mutate;
|
||||
import org.gradle.api.plugins.ExtensionContainer;
|
||||
import org.gradle.nativeplatform.test.googletest.GoogleTestTestSuiteBinarySpec;
|
||||
import org.gradle.model.RuleSource;
|
||||
import org.gradle.model.Validate;
|
||||
import org.gradle.nativeplatform.NativeExecutableBinarySpec
|
||||
import org.gradle.nativeplatform.NativeBinarySpec;
|
||||
import org.gradle.nativeplatform.NativeComponentSpec;
|
||||
import org.gradle.nativeplatform.NativeLibrarySpec;
|
||||
import org.gradle.nativeplatform.SharedLibraryBinarySpec;
|
||||
import org.gradle.nativeplatform.StaticLibraryBinarySpec;
|
||||
import org.gradle.nativeplatform.platform.internal.NativePlatformInternal;
|
||||
import org.gradle.nativeplatform.toolchain.NativeToolChain;
|
||||
import org.gradle.nativeplatform.toolchain.NativeToolChainRegistry;
|
||||
import org.gradle.nativeplatform.toolchain.internal.PlatformToolProvider;
|
||||
import org.gradle.nativeplatform.toolchain.internal.ToolType;
|
||||
import org.gradle.nativeplatform.toolchain.internal.gcc.AbstractGccCompatibleToolChain;
|
||||
import org.gradle.nativeplatform.toolchain.internal.msvcpp.VisualCppToolChain;
|
||||
import org.gradle.nativeplatform.toolchain.internal.tools.ToolRegistry;
|
||||
import org.gradle.platform.base.BinarySpec;
|
||||
import org.gradle.platform.base.ComponentSpec;
|
||||
import org.gradle.platform.base.ComponentSpecContainer;
|
||||
import org.gradle.platform.base.BinaryContainer;
|
||||
import org.gradle.platform.base.ComponentType;
|
||||
import org.gradle.platform.base.TypeBuilder;
|
||||
import org.gradle.nativeplatform.tasks.ObjectFilesToBinary;
|
||||
import groovy.transform.CompileStatic;
|
||||
import groovy.transform.CompileDynamic
|
||||
import org.gradle.nativeplatform.BuildTypeContainer
|
||||
|
||||
@CompileStatic
|
||||
class DisableBuildingGTest implements Plugin<Project> {
|
||||
@CompileStatic
|
||||
public void apply(Project project) {
|
||||
|
||||
}
|
||||
|
||||
@CompileStatic
|
||||
static class Rules extends RuleSource {
|
||||
@CompileDynamic
|
||||
private static void setBuildableFalseDynamically(NativeBinarySpec binary) {
|
||||
binary.buildable = false
|
||||
}
|
||||
|
||||
@Validate
|
||||
@CompileStatic
|
||||
// TODO: Move this to tc plugin
|
||||
void disableCrossTests(BinaryContainer binaries, ExtensionContainer extContainer) {
|
||||
final ToolchainExtension ext = extContainer.getByType(ToolchainExtension.class);
|
||||
|
||||
for (GoogleTestTestSuiteBinarySpec binary : binaries.withType(GoogleTestTestSuiteBinarySpec.class)) {
|
||||
if (ext.getCrossCompilers().findByName(binary.getTargetPlatform().getName()) != null) {
|
||||
setBuildableFalseDynamically(binary)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
48
buildSrc/src/main/groovy/JREArtifact.groovy
Normal file
48
buildSrc/src/main/groovy/JREArtifact.groovy
Normal file
@@ -0,0 +1,48 @@
|
||||
import groovy.transform.CompileStatic
|
||||
import javax.inject.Inject
|
||||
import jaci.gradle.deploy.artifact.MavenArtifact
|
||||
import jaci.gradle.deploy.context.DeployContext
|
||||
import org.gradle.api.Project
|
||||
import jaci.gradle.ActionWrapper
|
||||
|
||||
import java.util.function.Function
|
||||
|
||||
@CompileStatic
|
||||
class JREArtifact extends MavenArtifact {
|
||||
Function<DeployContext, Boolean> buildRequiresJre = (Function<DeployContext, Boolean>){ true }
|
||||
|
||||
void setJreDependency(String dep) {
|
||||
dependency = project.dependencies.add(configuration(), dep)
|
||||
}
|
||||
|
||||
@Inject
|
||||
JREArtifact(String name, Project project) {
|
||||
super(name, project)
|
||||
configuration = project.configurations.create(configuration())
|
||||
|
||||
onlyIf = { DeployContext ctx ->
|
||||
(buildRequiresJre.apply(ctx) && jreMissing(ctx)) || project.hasProperty("force-redeploy-jre")
|
||||
}
|
||||
|
||||
predeploy << new ActionWrapper({ DeployContext ctx ->
|
||||
ctx.logger.log('Deploying RoboRIO JRE (this will take a while)...')
|
||||
})
|
||||
|
||||
directory = '/tmp'
|
||||
filename = 'frcjre.ipk'
|
||||
|
||||
postdeploy << new ActionWrapper({ DeployContext ctx ->
|
||||
ctx.logger.log('Installing JRE...')
|
||||
ctx.execute('opkg remove frc2020-openjdk*; opkg install /tmp/frcjre.ipk; rm /tmp/frcjre.ipk')
|
||||
ctx.logger.log('JRE Deployed!')
|
||||
})
|
||||
}
|
||||
|
||||
String configuration() {
|
||||
return name + 'frcjre'
|
||||
}
|
||||
|
||||
boolean jreMissing(DeployContext ctx) {
|
||||
return ctx.execute('if [[ -f "/usr/local/frc/JRE/bin/java" ]]; then echo OK; else echo MISSING; fi').result.contains("MISSING")
|
||||
}
|
||||
}
|
||||
@@ -1,95 +1,74 @@
|
||||
|
||||
import org.gradle.api.GradleException;
|
||||
import org.gradle.api.Plugin;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.Task;
|
||||
import org.gradle.api.file.FileTree;
|
||||
import org.gradle.api.tasks.compile.JavaCompile;
|
||||
import org.gradle.language.base.internal.ProjectLayout;
|
||||
import org.gradle.language.base.plugins.ComponentModelBasePlugin;
|
||||
import org.gradle.language.nativeplatform.tasks.AbstractNativeSourceCompileTask;
|
||||
import org.gradle.model.ModelMap;
|
||||
import org.gradle.model.Mutate;
|
||||
import org.gradle.nativeplatform.test.googletest.GoogleTestTestSuiteBinarySpec;
|
||||
import org.gradle.model.RuleSource;
|
||||
import org.gradle.model.Validate;
|
||||
import org.gradle.nativeplatform.NativeExecutableBinarySpec
|
||||
import org.gradle.nativeplatform.NativeBinarySpec;
|
||||
import org.gradle.nativeplatform.NativeComponentSpec;
|
||||
import org.gradle.nativeplatform.NativeLibrarySpec;
|
||||
import org.gradle.nativeplatform.SharedLibraryBinarySpec;
|
||||
import org.gradle.nativeplatform.StaticLibraryBinarySpec;
|
||||
import org.gradle.nativeplatform.platform.internal.NativePlatformInternal;
|
||||
import org.gradle.nativeplatform.toolchain.NativeToolChain;
|
||||
import org.gradle.nativeplatform.toolchain.NativeToolChainRegistry;
|
||||
import org.gradle.nativeplatform.toolchain.internal.PlatformToolProvider;
|
||||
import org.gradle.nativeplatform.toolchain.internal.ToolType;
|
||||
import org.gradle.nativeplatform.toolchain.internal.gcc.AbstractGccCompatibleToolChain;
|
||||
import org.gradle.nativeplatform.toolchain.internal.msvcpp.VisualCppToolChain;
|
||||
import org.gradle.nativeplatform.toolchain.internal.tools.ToolRegistry;
|
||||
import org.gradle.platform.base.BinarySpec;
|
||||
import org.gradle.platform.base.ComponentSpec;
|
||||
import org.gradle.platform.base.ComponentSpecContainer;
|
||||
import org.gradle.platform.base.BinaryContainer;
|
||||
import org.gradle.platform.base.ComponentType;
|
||||
import org.gradle.platform.base.TypeBuilder;
|
||||
import org.gradle.nativeplatform.tasks.ObjectFilesToBinary;
|
||||
import groovy.transform.CompileStatic;
|
||||
import groovy.transform.CompileDynamic
|
||||
import org.gradle.nativeplatform.BuildTypeContainer
|
||||
|
||||
@CompileStatic
|
||||
class MultiBuilds implements Plugin<Project> {
|
||||
@CompileStatic
|
||||
public void apply(Project project) {
|
||||
|
||||
}
|
||||
|
||||
@CompileStatic
|
||||
static class Rules extends RuleSource {
|
||||
@Mutate
|
||||
void setupBuildTypes(BuildTypeContainer buildTypes, ProjectLayout projectLayout) {
|
||||
def project = (Project) projectLayout.projectIdentifier
|
||||
if (project.hasProperty('releaseBuild')) {
|
||||
buildTypes.create('debug')
|
||||
} else {
|
||||
buildTypes.create('release')
|
||||
}
|
||||
}
|
||||
|
||||
@CompileDynamic
|
||||
private static void setBuildableFalseDynamically(NativeBinarySpec binary) {
|
||||
binary.buildable = false
|
||||
}
|
||||
|
||||
@Mutate
|
||||
@CompileStatic
|
||||
void disableReleaseGoogleTest(BinaryContainer binaries, ProjectLayout projectLayout) {
|
||||
def project = (Project) projectLayout.projectIdentifier
|
||||
if (project.hasProperty('testRelease')) {
|
||||
return
|
||||
}
|
||||
binaries.withType(GoogleTestTestSuiteBinarySpec) { oSpec ->
|
||||
GoogleTestTestSuiteBinarySpec spec = (GoogleTestTestSuiteBinarySpec) oSpec
|
||||
if (spec.buildType.name == 'release') {
|
||||
Rules.setBuildableFalseDynamically(spec)
|
||||
}
|
||||
}
|
||||
// def crossCompileConfigs = []
|
||||
// for (BuildConfig config : configs) {
|
||||
// if (!BuildConfigRulesBase.isCrossCompile(config)) {
|
||||
// continue
|
||||
// }
|
||||
// crossCompileConfigs << config.architecture
|
||||
// }
|
||||
// if (!crossCompileConfigs.empty) {
|
||||
// binaries.withType(GoogleTestTestSuiteBinarySpec) { oSpec ->
|
||||
// GoogleTestTestSuiteBinarySpec spec = (GoogleTestTestSuiteBinarySpec) oSpec
|
||||
// if (crossCompileConfigs.contains(spec.targetPlatform.architecture.name)) {
|
||||
// setBuildableFalseDynamically(spec)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
import org.gradle.api.GradleException;
|
||||
import org.gradle.api.Plugin;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.Task;
|
||||
import org.gradle.api.file.FileTree;
|
||||
import org.gradle.api.tasks.compile.JavaCompile;
|
||||
import org.gradle.language.base.internal.ProjectLayout;
|
||||
import org.gradle.language.base.plugins.ComponentModelBasePlugin;
|
||||
import org.gradle.language.nativeplatform.tasks.AbstractNativeSourceCompileTask;
|
||||
import org.gradle.model.ModelMap;
|
||||
import edu.wpi.first.toolchain.ToolchainExtension
|
||||
import org.gradle.model.Mutate;
|
||||
import org.gradle.api.plugins.ExtensionContainer;
|
||||
import org.gradle.nativeplatform.test.googletest.GoogleTestTestSuiteBinarySpec;
|
||||
import org.gradle.model.RuleSource;
|
||||
import org.gradle.model.Validate;
|
||||
import org.gradle.nativeplatform.test.tasks.RunTestExecutable
|
||||
import org.gradle.nativeplatform.NativeExecutableBinarySpec
|
||||
import org.gradle.nativeplatform.NativeBinarySpec;
|
||||
import org.gradle.nativeplatform.NativeComponentSpec;
|
||||
import org.gradle.nativeplatform.NativeLibrarySpec;
|
||||
import org.gradle.nativeplatform.SharedLibraryBinarySpec;
|
||||
import org.gradle.nativeplatform.StaticLibraryBinarySpec;
|
||||
import org.gradle.nativeplatform.platform.internal.NativePlatformInternal;
|
||||
import org.gradle.nativeplatform.toolchain.NativeToolChain;
|
||||
import org.gradle.nativeplatform.toolchain.NativeToolChainRegistry;
|
||||
import org.gradle.nativeplatform.toolchain.internal.PlatformToolProvider;
|
||||
import org.gradle.nativeplatform.toolchain.internal.ToolType;
|
||||
import org.gradle.nativeplatform.toolchain.internal.gcc.AbstractGccCompatibleToolChain;
|
||||
import org.gradle.nativeplatform.toolchain.internal.msvcpp.VisualCppToolChain;
|
||||
import org.gradle.nativeplatform.toolchain.internal.tools.ToolRegistry;
|
||||
import org.gradle.platform.base.BinarySpec;
|
||||
import org.gradle.platform.base.ComponentSpec;
|
||||
import org.gradle.platform.base.ComponentSpecContainer;
|
||||
import org.gradle.platform.base.BinaryContainer;
|
||||
import org.gradle.platform.base.ComponentType;
|
||||
import org.gradle.platform.base.TypeBuilder;
|
||||
import org.gradle.nativeplatform.tasks.ObjectFilesToBinary;
|
||||
import groovy.transform.CompileStatic;
|
||||
import groovy.transform.CompileDynamic
|
||||
import org.gradle.nativeplatform.BuildTypeContainer
|
||||
|
||||
@CompileStatic
|
||||
class MultiBuilds implements Plugin<Project> {
|
||||
@CompileStatic
|
||||
public void apply(Project project) {
|
||||
|
||||
}
|
||||
|
||||
@CompileStatic
|
||||
static class Rules extends RuleSource {
|
||||
@CompileDynamic
|
||||
private static void setBuildableFalseDynamically(NativeBinarySpec binary) {
|
||||
binary.buildable = false
|
||||
}
|
||||
|
||||
|
||||
@Mutate
|
||||
@CompileStatic
|
||||
void disableReleaseGoogleTest(BinaryContainer binaries, ProjectLayout projectLayout) {
|
||||
def project = (Project) projectLayout.projectIdentifier
|
||||
if (project.hasProperty('testRelease')) {
|
||||
return
|
||||
}
|
||||
binaries.withType(GoogleTestTestSuiteBinarySpec) { oSpec ->
|
||||
GoogleTestTestSuiteBinarySpec spec = (GoogleTestTestSuiteBinarySpec) oSpec
|
||||
if (spec.buildType.name == 'release') {
|
||||
Rules.setBuildableFalseDynamically(spec)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ import org.gradle.platform.base.ComponentType;
|
||||
import org.gradle.platform.base.TypeBuilder;
|
||||
import org.gradle.nativeplatform.tasks.ObjectFilesToBinary;
|
||||
import groovy.transform.CompileStatic;
|
||||
import edu.wpi.first.nativeutils.tasks.ExportsGenerationTask
|
||||
|
||||
@CompileStatic
|
||||
class SingleNativeBuild implements Plugin<Project> {
|
||||
@@ -50,6 +51,22 @@ class SingleNativeBuild implements Plugin<Project> {
|
||||
|
||||
@CompileStatic
|
||||
static class Rules extends RuleSource {
|
||||
@Mutate
|
||||
@CompileStatic
|
||||
void removeMacSystemIncludes(ModelMap<Task> tasks, BinaryContainer binaries) {
|
||||
binaries.each {
|
||||
if (!(it instanceof NativeBinarySpec)) {
|
||||
return
|
||||
}
|
||||
NativeBinarySpec nativeBin = (NativeBinarySpec)it
|
||||
if (nativeBin.targetPlatform.operatingSystem.isMacOsX()) {
|
||||
nativeBin.tasks.withType(AbstractNativeSourceCompileTask) { AbstractNativeSourceCompileTask compileTask->
|
||||
compileTask.getSystemIncludes().setFrom()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Mutate
|
||||
@CompileStatic
|
||||
void setupSingleNativeBuild(ModelMap<Task> tasks, ComponentSpecContainer components, BinaryContainer binaryContainer, ProjectLayout projectLayout) {
|
||||
@@ -78,8 +95,7 @@ class SingleNativeBuild implements Plugin<Project> {
|
||||
return
|
||||
}
|
||||
def tmpBaseBin = (NativeBinarySpec) oTmpBaseBin
|
||||
if (tmpBaseBin.targetPlatform.operatingSystem.name == binary.targetPlatform.operatingSystem.name &&
|
||||
tmpBaseBin.targetPlatform.architecture.name == binary.targetPlatform.architecture.name &&
|
||||
if (tmpBaseBin.targetPlatform.name == binary.targetPlatform.name &&
|
||||
tmpBaseBin.buildType == binary.buildType) {
|
||||
baseBin = tmpBaseBin
|
||||
}
|
||||
@@ -89,6 +105,10 @@ class SingleNativeBuild implements Plugin<Project> {
|
||||
if (binary instanceof SharedLibraryBinarySpec) {
|
||||
def sBinary = (SharedLibraryBinarySpec) binary
|
||||
ObjectFilesToBinary link = (ObjectFilesToBinary) sBinary.tasks.link
|
||||
ExportsGenerationTask exportsTask = binary.tasks.withType(ExportsGenerationTask)[0]
|
||||
if (exportsTask != null) {
|
||||
exportsTask.dependsOn compileTask
|
||||
}
|
||||
link.dependsOn compileTask
|
||||
link.inputs.dir compileTask.objectFileDir
|
||||
def tree = project.fileTree(compileTask.objectFileDir)
|
||||
|
||||
@@ -7,16 +7,12 @@ cppSrcFileInclude {
|
||||
\.cpp$
|
||||
}
|
||||
|
||||
modifiableFileExclude {
|
||||
\.so$
|
||||
}
|
||||
|
||||
repoRootNameOverride {
|
||||
cameraserver
|
||||
}
|
||||
|
||||
includeOtherLibs {
|
||||
^HAL/
|
||||
^hal/
|
||||
^networktables/
|
||||
^opencv2/
|
||||
^support/
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
project(cameraserver)
|
||||
|
||||
include(CompileWarnings)
|
||||
include(AddTest)
|
||||
|
||||
find_package( OpenCV REQUIRED )
|
||||
|
||||
# Java bindings
|
||||
@@ -32,6 +35,7 @@ set_target_properties(cameraserver PROPERTIES DEBUG_POSTFIX "d")
|
||||
target_include_directories(cameraserver PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/main/native/include>
|
||||
$<INSTALL_INTERFACE:${include_dest}/cameraserver>)
|
||||
wpilib_target_warnings(cameraserver)
|
||||
target_link_libraries(cameraserver PUBLIC ntcore cscore wpiutil ${OpenCV_LIBS})
|
||||
|
||||
set_property(TARGET cameraserver PROPERTY FOLDER "libraries")
|
||||
@@ -43,15 +47,24 @@ if (NOT WITHOUT_JAVA AND MSVC)
|
||||
install(TARGETS cameraserver RUNTIME DESTINATION "${jni_lib_dest}" COMPONENT Runtime)
|
||||
endif()
|
||||
|
||||
if (MSVC)
|
||||
if (MSVC OR FLAT_INSTALL_WPILIB)
|
||||
set (cameraserver_config_dir ${wpilib_dest})
|
||||
else()
|
||||
set (cameraserver_config_dir share/cameraserver)
|
||||
endif()
|
||||
|
||||
install(FILES cameraserver-config.cmake DESTINATION ${cameraserver_config_dir})
|
||||
configure_file(cameraserver-config.cmake.in ${CMAKE_BINARY_DIR}/cameraserver-config.cmake )
|
||||
install(FILES ${CMAKE_BINARY_DIR}/cameraserver-config.cmake DESTINATION ${cameraserver_config_dir})
|
||||
install(EXPORT cameraserver DESTINATION ${cameraserver_config_dir})
|
||||
|
||||
file(GLOB multiCameraServer_src multiCameraServer/src/main/native/cpp/*.cpp)
|
||||
add_executable(multiCameraServer ${multiCameraServer_src})
|
||||
wpilib_target_warnings(multiCameraServer)
|
||||
target_link_libraries(multiCameraServer cameraserver)
|
||||
|
||||
set_property(TARGET multiCameraServer PROPERTY FOLDER "examples")
|
||||
|
||||
if (WITH_TESTS)
|
||||
wpilib_add_test(cameraserver src/test/native/cpp)
|
||||
target_link_libraries(cameraserver_test cameraserver gtest)
|
||||
endif()
|
||||
|
||||
@@ -10,12 +10,12 @@ evaluationDependsOn(':hal')
|
||||
apply from: "${rootDir}/shared/javacpp/setupBuild.gradle"
|
||||
|
||||
dependencies {
|
||||
compile project(':wpiutil')
|
||||
compile project(':ntcore')
|
||||
compile project(':cscore')
|
||||
devCompile project(':wpiutil')
|
||||
devCompile project(':ntcore')
|
||||
devCompile project(':cscore')
|
||||
implementation project(':wpiutil')
|
||||
implementation project(':ntcore')
|
||||
implementation project(':cscore')
|
||||
devImplementation project(':wpiutil')
|
||||
devImplementation project(':ntcore')
|
||||
devImplementation project(':cscore')
|
||||
}
|
||||
|
||||
ext {
|
||||
@@ -30,23 +30,20 @@ ext {
|
||||
|
||||
apply from: "${rootDir}/shared/opencv.gradle"
|
||||
|
||||
model {
|
||||
// Exports config is a utility to enable exporting all symbols in a C++ library on windows to a DLL.
|
||||
// This removes the need for DllExport on a library. However, the gradle C++ builder has a bug
|
||||
// where some extra symbols are added that cannot be resolved at link time. This configuration
|
||||
// lets you specify specific symbols to exlude from exporting.
|
||||
exportsConfigs {
|
||||
cameraserver(ExportsConfig) {
|
||||
x86ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure',
|
||||
'_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure',
|
||||
'_TI5?AVfailure', '_CT??_R0?AVout_of_range', '_CTA3?AVout_of_range',
|
||||
'_TI3?AVout_of_range', '_CT??_R0?AVbad_cast']
|
||||
x64ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure',
|
||||
'_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure',
|
||||
'_TI5?AVfailure', '_CT??_R0?AVout_of_range', '_CTA3?AVout_of_range',
|
||||
'_TI3?AVout_of_range', '_CT??_R0?AVbad_cast']
|
||||
}
|
||||
nativeUtils.exportsConfigs {
|
||||
cameraserver {
|
||||
x86ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure',
|
||||
'_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure',
|
||||
'_TI5?AVfailure', '_CT??_R0?AVout_of_range', '_CTA3?AVout_of_range',
|
||||
'_TI3?AVout_of_range', '_CT??_R0?AVbad_cast']
|
||||
x64ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure',
|
||||
'_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure',
|
||||
'_TI5?AVfailure', '_CT??_R0?AVout_of_range', '_CTA3?AVout_of_range',
|
||||
'_TI3?AVout_of_range', '_CT??_R0?AVbad_cast']
|
||||
}
|
||||
}
|
||||
|
||||
model {
|
||||
components {}
|
||||
binaries {
|
||||
all {
|
||||
@@ -66,7 +63,7 @@ model {
|
||||
if (it in NativeExecutableSpec && it.name == "${nativeName}Dev") {
|
||||
it.binaries.each {
|
||||
if (!found) {
|
||||
def arch = it.targetPlatform.architecture.name
|
||||
def arch = it.targetPlatform.name
|
||||
if (arch == systemArch) {
|
||||
def filePath = it.tasks.install.installDirectory.get().toString() + File.separatorChar + 'lib'
|
||||
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
include(CMakeFindDependencyMacro)
|
||||
find_dependency(wpiutil)
|
||||
find_dependency(ntcore)
|
||||
find_dependency(cscore)
|
||||
find_dependency(OpenCV)
|
||||
|
||||
get_filename_component(SELF_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
|
||||
include(${SELF_DIR}/cameraserver.cmake)
|
||||
8
cameraserver/cameraserver-config.cmake.in
Normal file
8
cameraserver/cameraserver-config.cmake.in
Normal file
@@ -0,0 +1,8 @@
|
||||
include(CMakeFindDependencyMacro)
|
||||
@FILENAME_DEP_REPLACE@
|
||||
@WPIUTIL_DEP_REPLACE@
|
||||
@NTCORE_DEP_REPLACE@
|
||||
@CSCORE_DEP_REPLACE@
|
||||
find_dependency(OpenCV)
|
||||
|
||||
include(${SELF_DIR}/cameraserver.cmake)
|
||||
@@ -27,12 +27,12 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile 'com.google.code.gson:gson:2.8.5'
|
||||
implementation 'com.google.code.gson:gson:2.8.5'
|
||||
|
||||
compile project(':wpiutil')
|
||||
compile project(':ntcore')
|
||||
compile project(':cscore')
|
||||
compile project(':cameraserver')
|
||||
implementation project(':wpiutil')
|
||||
implementation project(':ntcore')
|
||||
implementation project(':cscore')
|
||||
implementation project(':cameraserver')
|
||||
}
|
||||
|
||||
model {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
@@ -9,8 +9,9 @@ package edu.wpi.first.cameraserver;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Hashtable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import edu.wpi.cscore.AxisCamera;
|
||||
@@ -142,17 +143,21 @@ public final class CameraServer {
|
||||
values[j] = "mjpg:" + values[j];
|
||||
}
|
||||
|
||||
// Look to see if we have a passthrough server for this source
|
||||
for (VideoSink i : m_sinks.values()) {
|
||||
int sink = i.getHandle();
|
||||
int sinkSource = CameraServerJNI.getSinkSource(sink);
|
||||
if (source == sinkSource
|
||||
&& VideoSink.getKindFromInt(CameraServerJNI.getSinkKind(sink)) == VideoSink.Kind.kMjpeg) {
|
||||
// Add USB-only passthrough
|
||||
String[] finalValues = Arrays.copyOf(values, values.length + 1);
|
||||
int port = CameraServerJNI.getMjpegServerPort(sink);
|
||||
finalValues[values.length] = makeStreamValue("172.22.11.2", port);
|
||||
return finalValues;
|
||||
if (CameraServerSharedStore.getCameraServerShared().isRoboRIO()) {
|
||||
// Look to see if we have a passthrough server for this source
|
||||
// Only do this on the roboRIO
|
||||
for (VideoSink i : m_sinks.values()) {
|
||||
int sink = i.getHandle();
|
||||
int sinkSource = CameraServerJNI.getSinkSource(sink);
|
||||
if (source == sinkSource
|
||||
&& VideoSink.getKindFromInt(CameraServerJNI.getSinkKind(sink))
|
||||
== VideoSink.Kind.kMjpeg) {
|
||||
// Add USB-only passthrough
|
||||
String[] finalValues = Arrays.copyOf(values, values.length + 1);
|
||||
int port = CameraServerJNI.getMjpegServerPort(sink);
|
||||
finalValues[values.length] = makeStreamValue("172.22.11.2", port);
|
||||
return finalValues;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,13 +171,9 @@ public final class CameraServer {
|
||||
int sink = i.getHandle();
|
||||
|
||||
// Get the source's subtable (if none exists, we're done)
|
||||
int source;
|
||||
Integer fixedSource = m_fixedSources.get(sink);
|
||||
if (fixedSource != null) {
|
||||
source = fixedSource;
|
||||
} else {
|
||||
source = CameraServerJNI.getSinkSource(sink);
|
||||
}
|
||||
int source = Objects.requireNonNullElseGet(m_fixedSources.get(sink),
|
||||
() -> CameraServerJNI.getSinkSource(sink));
|
||||
|
||||
if (source == 0) {
|
||||
continue;
|
||||
}
|
||||
@@ -301,10 +302,10 @@ public final class CameraServer {
|
||||
"PMD.NPathComplexity"})
|
||||
private CameraServer() {
|
||||
m_defaultUsbDevice = new AtomicInteger();
|
||||
m_sources = new Hashtable<>();
|
||||
m_sinks = new Hashtable<>();
|
||||
m_fixedSources = new Hashtable<>();
|
||||
m_tables = new Hashtable<>();
|
||||
m_sources = new HashMap<>();
|
||||
m_sinks = new HashMap<>();
|
||||
m_fixedSources = new HashMap<>();
|
||||
m_tables = new HashMap<>();
|
||||
m_publishTable = NetworkTableInstance.getDefault().getTable(kPublishName);
|
||||
m_nextPort = kBasePort;
|
||||
m_addresses = new String[0];
|
||||
@@ -615,7 +616,9 @@ public final class CameraServer {
|
||||
// create a dummy CvSource
|
||||
CvSource source = new CvSource(name, VideoMode.PixelFormat.kMJPEG, 160, 120, 30);
|
||||
MjpegServer server = startAutomaticCapture(source);
|
||||
m_fixedSources.put(server.getHandle(), source.getHandle());
|
||||
synchronized (this) {
|
||||
m_fixedSources.put(server.getHandle(), source.getHandle());
|
||||
}
|
||||
|
||||
return server;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
@@ -43,4 +43,13 @@ public interface CameraServerShared {
|
||||
* @param id the usage id
|
||||
*/
|
||||
void reportAxisCamera(int id);
|
||||
|
||||
/**
|
||||
* Get if running on a roboRIO.
|
||||
*
|
||||
* @return true if on roboRIO
|
||||
*/
|
||||
default boolean isRoboRIO() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
@@ -77,7 +77,7 @@ public class VisionRunner<P extends VisionPipeline> {
|
||||
public void runOnce() {
|
||||
Long id = CameraServerSharedStore.getCameraServerShared().getRobotMainThreadId();
|
||||
|
||||
if (id != null && Thread.currentThread().getId() == id.longValue()) {
|
||||
if (id != null && Thread.currentThread().getId() == id) {
|
||||
throw new IllegalStateException(
|
||||
"VisionRunner.runOnce() cannot be called from the main robot thread");
|
||||
}
|
||||
@@ -110,7 +110,7 @@ public class VisionRunner<P extends VisionPipeline> {
|
||||
public void runForever() {
|
||||
Long id = CameraServerSharedStore.getCameraServerShared().getRobotMainThreadId();
|
||||
|
||||
if (id != null && Thread.currentThread().getId() == id.longValue()) {
|
||||
if (id != null && Thread.currentThread().getId() == id) {
|
||||
throw new IllegalStateException(
|
||||
"VisionRunner.runForever() cannot be called from the main robot thread");
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <networktables/NetworkTable.h>
|
||||
#include <networktables/NetworkTableInstance.h>
|
||||
#include <wpi/DenseMap.h>
|
||||
#include <wpi/ManagedStatic.h>
|
||||
#include <wpi/SmallString.h>
|
||||
#include <wpi/StringMap.h>
|
||||
#include <wpi/mutex.h>
|
||||
@@ -47,8 +48,14 @@ struct CameraServer::Impl {
|
||||
};
|
||||
|
||||
CameraServer* CameraServer::GetInstance() {
|
||||
static CameraServer instance;
|
||||
return &instance;
|
||||
struct Creator {
|
||||
static void* call() { return new CameraServer{}; }
|
||||
};
|
||||
struct Deleter {
|
||||
static void call(void* ptr) { delete static_cast<CameraServer*>(ptr); }
|
||||
};
|
||||
static wpi::ManagedStatic<CameraServer, Creator, Deleter> instance;
|
||||
return &(*instance);
|
||||
}
|
||||
|
||||
static wpi::StringRef MakeSourceValue(CS_Source source,
|
||||
@@ -56,21 +63,21 @@ static wpi::StringRef MakeSourceValue(CS_Source source,
|
||||
CS_Status status = 0;
|
||||
buf.clear();
|
||||
switch (cs::GetSourceKind(source, &status)) {
|
||||
case cs::VideoSource::kUsb: {
|
||||
case CS_SOURCE_USB: {
|
||||
wpi::StringRef prefix{"usb:"};
|
||||
buf.append(prefix.begin(), prefix.end());
|
||||
auto path = cs::GetUsbCameraPath(source, &status);
|
||||
buf.append(path.begin(), path.end());
|
||||
break;
|
||||
}
|
||||
case cs::VideoSource::kHttp: {
|
||||
case CS_SOURCE_HTTP: {
|
||||
wpi::StringRef prefix{"ip:"};
|
||||
buf.append(prefix.begin(), prefix.end());
|
||||
auto urls = cs::GetHttpCameraUrls(source, &status);
|
||||
if (!urls.empty()) buf.append(urls[0].begin(), urls[0].end());
|
||||
break;
|
||||
}
|
||||
case cs::VideoSource::kCv:
|
||||
case CS_SOURCE_CV:
|
||||
return "cv:";
|
||||
default:
|
||||
return "unknown:";
|
||||
@@ -87,7 +94,7 @@ static std::string MakeStreamValue(const wpi::Twine& address, int port) {
|
||||
|
||||
std::shared_ptr<nt::NetworkTable> CameraServer::Impl::GetSourceTable(
|
||||
CS_Source source) {
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
return m_tables.lookup(source);
|
||||
}
|
||||
|
||||
@@ -132,7 +139,9 @@ std::vector<std::string> CameraServer::Impl::GetSourceStreamValues(
|
||||
auto values = cs::GetHttpCameraUrls(source, &status);
|
||||
for (auto& value : values) value = "mjpg:" + value;
|
||||
|
||||
#ifdef __FRC_ROBORIO__
|
||||
// Look to see if we have a passthrough server for this source
|
||||
// Only do this on the roboRIO
|
||||
for (const auto& i : m_sinks) {
|
||||
CS_Sink sink = i.second.GetHandle();
|
||||
CS_Source sinkSource = cs::GetSinkSource(sink, &status);
|
||||
@@ -144,13 +153,14 @@ std::vector<std::string> CameraServer::Impl::GetSourceStreamValues(
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Set table value
|
||||
return values;
|
||||
}
|
||||
|
||||
void CameraServer::Impl::UpdateStreamValues() {
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
// Over all the sinks...
|
||||
for (const auto& i : m_sinks) {
|
||||
CS_Status status = 0;
|
||||
@@ -239,14 +249,14 @@ static void PutSourcePropertyValue(nt::NetworkTable* table,
|
||||
CS_Status status = 0;
|
||||
nt::NetworkTableEntry entry = table->GetEntry(name);
|
||||
switch (event.propertyKind) {
|
||||
case cs::VideoProperty::kBoolean:
|
||||
case CS_PROP_BOOLEAN:
|
||||
if (isNew)
|
||||
entry.SetDefaultBoolean(event.value != 0);
|
||||
else
|
||||
entry.SetBoolean(event.value != 0);
|
||||
break;
|
||||
case cs::VideoProperty::kInteger:
|
||||
case cs::VideoProperty::kEnum:
|
||||
case CS_PROP_INTEGER:
|
||||
case CS_PROP_ENUM:
|
||||
if (isNew) {
|
||||
entry.SetDefaultDouble(event.value);
|
||||
table->GetEntry(infoName + "/min")
|
||||
@@ -261,7 +271,7 @@ static void PutSourcePropertyValue(nt::NetworkTable* table,
|
||||
entry.SetDouble(event.value);
|
||||
}
|
||||
break;
|
||||
case cs::VideoProperty::kString:
|
||||
case CS_PROP_STRING:
|
||||
if (isNew)
|
||||
entry.SetDefaultString(event.valueStr);
|
||||
else
|
||||
@@ -296,7 +306,7 @@ CameraServer::Impl::Impl()
|
||||
// Create subtable for the camera
|
||||
auto table = m_publishTable->GetSubTable(event.name);
|
||||
{
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
m_tables.insert(std::make_pair(event.sourceHandle, table));
|
||||
}
|
||||
wpi::SmallString<64> buf;
|
||||
@@ -561,7 +571,7 @@ cs::CvSink CameraServer::GetVideo() {
|
||||
cs::VideoSource source;
|
||||
{
|
||||
auto csShared = GetCameraServerShared();
|
||||
std::lock_guard<wpi::mutex> lock(m_impl->m_mutex);
|
||||
std::scoped_lock lock(m_impl->m_mutex);
|
||||
if (m_impl->m_primarySourceName.empty()) {
|
||||
csShared->SetCameraServerError("no camera available");
|
||||
return cs::CvSink{};
|
||||
@@ -581,7 +591,7 @@ cs::CvSink CameraServer::GetVideo(const cs::VideoSource& camera) {
|
||||
name += camera.GetName();
|
||||
|
||||
{
|
||||
std::lock_guard<wpi::mutex> lock(m_impl->m_mutex);
|
||||
std::scoped_lock lock(m_impl->m_mutex);
|
||||
auto it = m_impl->m_sinks.find(name);
|
||||
if (it != m_impl->m_sinks.end()) {
|
||||
auto kind = it->second.GetKind();
|
||||
@@ -606,7 +616,7 @@ cs::CvSink CameraServer::GetVideo(const wpi::Twine& name) {
|
||||
wpi::StringRef nameStr = name.toStringRef(nameBuf);
|
||||
cs::VideoSource source;
|
||||
{
|
||||
std::lock_guard<wpi::mutex> lock(m_impl->m_mutex);
|
||||
std::scoped_lock lock(m_impl->m_mutex);
|
||||
auto it = m_impl->m_sources.find(nameStr);
|
||||
if (it == m_impl->m_sources.end()) {
|
||||
auto csShared = GetCameraServerShared();
|
||||
@@ -628,7 +638,7 @@ cs::CvSource CameraServer::PutVideo(const wpi::Twine& name, int width,
|
||||
cs::MjpegServer CameraServer::AddServer(const wpi::Twine& name) {
|
||||
int port;
|
||||
{
|
||||
std::lock_guard<wpi::mutex> lock(m_impl->m_mutex);
|
||||
std::scoped_lock lock(m_impl->m_mutex);
|
||||
port = m_impl->m_nextPort++;
|
||||
}
|
||||
return AddServer(name, port);
|
||||
@@ -641,12 +651,12 @@ cs::MjpegServer CameraServer::AddServer(const wpi::Twine& name, int port) {
|
||||
}
|
||||
|
||||
void CameraServer::AddServer(const cs::VideoSink& server) {
|
||||
std::lock_guard<wpi::mutex> lock(m_impl->m_mutex);
|
||||
std::scoped_lock lock(m_impl->m_mutex);
|
||||
m_impl->m_sinks.try_emplace(server.GetName(), server);
|
||||
}
|
||||
|
||||
void CameraServer::RemoveServer(const wpi::Twine& name) {
|
||||
std::lock_guard<wpi::mutex> lock(m_impl->m_mutex);
|
||||
std::scoped_lock lock(m_impl->m_mutex);
|
||||
wpi::SmallString<64> nameBuf;
|
||||
m_impl->m_sinks.erase(name.toStringRef(nameBuf));
|
||||
}
|
||||
@@ -654,7 +664,7 @@ void CameraServer::RemoveServer(const wpi::Twine& name) {
|
||||
cs::VideoSink CameraServer::GetServer() {
|
||||
wpi::SmallString<64> name;
|
||||
{
|
||||
std::lock_guard<wpi::mutex> lock(m_impl->m_mutex);
|
||||
std::scoped_lock lock(m_impl->m_mutex);
|
||||
if (m_impl->m_primarySourceName.empty()) {
|
||||
auto csShared = GetCameraServerShared();
|
||||
csShared->SetCameraServerError("no camera available");
|
||||
@@ -669,7 +679,7 @@ cs::VideoSink CameraServer::GetServer() {
|
||||
cs::VideoSink CameraServer::GetServer(const wpi::Twine& name) {
|
||||
wpi::SmallString<64> nameBuf;
|
||||
wpi::StringRef nameStr = name.toStringRef(nameBuf);
|
||||
std::lock_guard<wpi::mutex> lock(m_impl->m_mutex);
|
||||
std::scoped_lock lock(m_impl->m_mutex);
|
||||
auto it = m_impl->m_sinks.find(nameStr);
|
||||
if (it == m_impl->m_sinks.end()) {
|
||||
auto csShared = GetCameraServerShared();
|
||||
@@ -681,19 +691,19 @@ cs::VideoSink CameraServer::GetServer(const wpi::Twine& name) {
|
||||
|
||||
void CameraServer::AddCamera(const cs::VideoSource& camera) {
|
||||
std::string name = camera.GetName();
|
||||
std::lock_guard<wpi::mutex> lock(m_impl->m_mutex);
|
||||
std::scoped_lock lock(m_impl->m_mutex);
|
||||
if (m_impl->m_primarySourceName.empty()) m_impl->m_primarySourceName = name;
|
||||
m_impl->m_sources.try_emplace(name, camera);
|
||||
}
|
||||
|
||||
void CameraServer::RemoveCamera(const wpi::Twine& name) {
|
||||
std::lock_guard<wpi::mutex> lock(m_impl->m_mutex);
|
||||
std::scoped_lock lock(m_impl->m_mutex);
|
||||
wpi::SmallString<64> nameBuf;
|
||||
m_impl->m_sources.erase(name.toStringRef(nameBuf));
|
||||
}
|
||||
|
||||
void CameraServer::SetSize(int size) {
|
||||
std::lock_guard<wpi::mutex> lock(m_impl->m_mutex);
|
||||
std::scoped_lock lock(m_impl->m_mutex);
|
||||
if (m_impl->m_primarySourceName.empty()) return;
|
||||
auto it = m_impl->m_sources.find(m_impl->m_primarySourceName);
|
||||
if (it == m_impl->m_sources.end()) return;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
@@ -24,20 +24,22 @@ class DefaultCameraServerShared : public frc::CameraServerShared {
|
||||
};
|
||||
} // namespace
|
||||
|
||||
namespace frc {
|
||||
|
||||
static std::unique_ptr<CameraServerShared> cameraServerShared = nullptr;
|
||||
static std::unique_ptr<frc::CameraServerShared> cameraServerShared = nullptr;
|
||||
static wpi::mutex setLock;
|
||||
|
||||
void SetCameraServerShared(std::unique_ptr<CameraServerShared> shared) {
|
||||
std::unique_lock<wpi::mutex> lock(setLock);
|
||||
cameraServerShared = std::move(shared);
|
||||
}
|
||||
namespace frc {
|
||||
CameraServerShared* GetCameraServerShared() {
|
||||
std::unique_lock<wpi::mutex> lock(setLock);
|
||||
std::unique_lock lock(setLock);
|
||||
if (!cameraServerShared) {
|
||||
cameraServerShared = std::make_unique<DefaultCameraServerShared>();
|
||||
}
|
||||
return cameraServerShared.get();
|
||||
}
|
||||
} // namespace frc
|
||||
|
||||
extern "C" {
|
||||
void CameraServer_SetCameraServerShared(frc::CameraServerShared* shared) {
|
||||
std::unique_lock lock(setLock);
|
||||
cameraServerShared.reset(shared);
|
||||
}
|
||||
} // extern "C"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2014-2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2014-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <wpi/Twine.h>
|
||||
|
||||
#include "cscore.h"
|
||||
#include "cscore_cv.h"
|
||||
|
||||
namespace frc {
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
@@ -26,6 +26,10 @@ class CameraServerShared {
|
||||
virtual std::pair<std::thread::id, bool> GetRobotMainThreadId() const = 0;
|
||||
};
|
||||
|
||||
void SetCameraServerShared(std::unique_ptr<CameraServerShared> shared);
|
||||
CameraServerShared* GetCameraServerShared();
|
||||
} // namespace frc
|
||||
|
||||
extern "C" {
|
||||
// Takes ownership
|
||||
void CameraServer_SetCameraServerShared(frc::CameraServerShared* shared);
|
||||
} // extern "C"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <memory>
|
||||
|
||||
#include "cscore.h"
|
||||
#include "cscore_cv.h"
|
||||
#include "vision/VisionPipeline.h"
|
||||
|
||||
namespace frc {
|
||||
|
||||
14
cmake/modules/AddTest.cmake
Normal file
14
cmake/modules/AddTest.cmake
Normal file
@@ -0,0 +1,14 @@
|
||||
include(CompileWarnings)
|
||||
|
||||
macro(wpilib_add_test name srcdir)
|
||||
file(GLOB_RECURSE test_src ${srcdir}/*.cpp)
|
||||
add_executable(${name}_test ${test_src})
|
||||
wpilib_target_warnings(${name}_test)
|
||||
if (BUILD_SHARED_LIBS)
|
||||
target_compile_definitions(${name}_test PRIVATE -DGTEST_LINKED_AS_SHARED_LIBRARY)
|
||||
endif()
|
||||
if (MSVC)
|
||||
target_compile_options(${name}_test PRIVATE /wd4251 /wd4101)
|
||||
endif()
|
||||
add_test(NAME ${name} COMMAND ${name}_test)
|
||||
endmacro()
|
||||
7
cmake/modules/CompileWarnings.cmake
Normal file
7
cmake/modules/CompileWarnings.cmake
Normal file
@@ -0,0 +1,7 @@
|
||||
macro(wpilib_target_warnings target)
|
||||
if(NOT MSVC)
|
||||
target_compile_options(${target} PRIVATE -Wall -pedantic -Wextra -Werror -Wno-unused-parameter -Wno-error=deprecated-declarations)
|
||||
else()
|
||||
target_compile_options(${target} PRIVATE /wd4244 /wd4267 /wd4146 /WX /wd4996)
|
||||
endif()
|
||||
endmacro()
|
||||
@@ -1,3 +1,4 @@
|
||||
set(SCRIPTS_DIR "${CMAKE_CURRENT_LIST_DIR}/../scripts")
|
||||
MACRO(GENERATE_RESOURCES inputDir outputDir prefix namespace outputFiles)
|
||||
FILE(GLOB inputFiles ${inputDir}/*)
|
||||
SET(${outputFiles})
|
||||
@@ -16,9 +17,9 @@ MACRO(GENERATE_RESOURCES inputDir outputDir prefix namespace outputFiles)
|
||||
"-Doutput=${output}"
|
||||
"-Dprefix=${prefix}"
|
||||
"-Dnamespace=${namespace}"
|
||||
-P "${CMAKE_SOURCE_DIR}/cmake/scripts/GenResource.cmake"
|
||||
-P "${SCRIPTS_DIR}/GenResource.cmake"
|
||||
MAIN_DEPENDENCY ${input}
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/cmake/scripts/GenResource.cmake
|
||||
DEPENDS ${SCRIPTS_DIR}/GenResource.cmake
|
||||
VERBATIM
|
||||
)
|
||||
ENDFOREACH()
|
||||
|
||||
4
cmake/toolchains/arm-frc-gnueabi.toolchain.cmake
Normal file
4
cmake/toolchains/arm-frc-gnueabi.toolchain.cmake
Normal file
@@ -0,0 +1,4 @@
|
||||
set(GCC_COMPILER_VERSION "" CACHE STRING "GCC Compiler version")
|
||||
set(GNU_MACHINE "arm-frc2020-linux-gnueabi" CACHE STRING "GNU compiler triple")
|
||||
set(SOFTFP yes)
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/arm.toolchain.cmake")
|
||||
98
cmake/toolchains/arm-pi-gnueabihf.toolchain.cmake
Normal file
98
cmake/toolchains/arm-pi-gnueabihf.toolchain.cmake
Normal file
@@ -0,0 +1,98 @@
|
||||
set(GCC_COMPILER_VERSION "" CACHE STRING "GCC Compiler version")
|
||||
set(GNU_MACHINE "arm-raspbian10-linux-gnueabi" CACHE STRING "GNU compiler triple")
|
||||
|
||||
if(COMMAND toolchain_save_config)
|
||||
return() # prevent recursive call
|
||||
endif()
|
||||
|
||||
set(CMAKE_SYSTEM_NAME Linux)
|
||||
set(CMAKE_SYSTEM_VERSION 1)
|
||||
if(NOT DEFINED CMAKE_SYSTEM_PROCESSOR)
|
||||
set(CMAKE_SYSTEM_PROCESSOR arm)
|
||||
else()
|
||||
#message("CMAKE_SYSTEM_PROCESSOR=${CMAKE_SYSTEM_PROCESSOR}")
|
||||
endif()
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/opencv/platforms/linux/gnu.toolchain.cmake")
|
||||
|
||||
if(CMAKE_SYSTEM_PROCESSOR STREQUAL arm AND NOT ARM_IGNORE_FP)
|
||||
set(FLOAT_ABI_SUFFIX "")
|
||||
if(NOT SOFTFP)
|
||||
set(FLOAT_ABI_SUFFIX "hf")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT "x${GCC_COMPILER_VERSION}" STREQUAL "x")
|
||||
set(__GCC_VER_SUFFIX "-${GCC_COMPILER_VERSION}")
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED CMAKE_C_COMPILER)
|
||||
find_program(CMAKE_C_COMPILER NAMES ${GNU_MACHINE}${FLOAT_ABI_SUFFIX}-gcc${__GCC_VER_SUFFIX})
|
||||
else()
|
||||
#message(WARNING "CMAKE_C_COMPILER=${CMAKE_C_COMPILER} is defined")
|
||||
endif()
|
||||
if(NOT DEFINED CMAKE_CXX_COMPILER)
|
||||
find_program(CMAKE_CXX_COMPILER NAMES ${GNU_MACHINE}${FLOAT_ABI_SUFFIX}-g++${__GCC_VER_SUFFIX})
|
||||
else()
|
||||
#message(WARNING "CMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} is defined")
|
||||
endif()
|
||||
if(NOT DEFINED CMAKE_LINKER)
|
||||
find_program(CMAKE_LINKER NAMES ${GNU_MACHINE}${FLOAT_ABI_SUFFIX}-ld${__GCC_VER_SUFFIX} ${GNU_MACHINE}${FLOAT_ABI_SUFFIX}-ld)
|
||||
else()
|
||||
#message(WARNING "CMAKE_LINKER=${CMAKE_LINKER} is defined")
|
||||
endif()
|
||||
if(NOT DEFINED CMAKE_AR)
|
||||
find_program(CMAKE_AR NAMES ${GNU_MACHINE}${FLOAT_ABI_SUFFIX}-ar${__GCC_VER_SUFFIX} ${GNU_MACHINE}${FLOAT_ABI_SUFFIX}-ar)
|
||||
else()
|
||||
#message(WARNING "CMAKE_AR=${CMAKE_AR} is defined")
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED ARM_LINUX_SYSROOT AND DEFINED GNU_MACHINE)
|
||||
set(ARM_LINUX_SYSROOT /usr/${GNU_MACHINE}${FLOAT_ABI_SUFFIX})
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED CMAKE_CXX_FLAGS)
|
||||
set(CMAKE_CXX_FLAGS "" CACHE INTERNAL "")
|
||||
set(CMAKE_C_FLAGS "" CACHE INTERNAL "")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "" CACHE INTERNAL "")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS "" CACHE INTERNAL "")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "" CACHE INTERNAL "")
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdata-sections -Wa,--noexecstack -fsigned-char -Wno-psabi")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fdata-sections -Wa,--noexecstack -fsigned-char -Wno-psabi")
|
||||
if(CMAKE_SYSTEM_PROCESSOR STREQUAL arm)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-z,nocopyreloc")
|
||||
endif()
|
||||
if(CMAKE_SYSTEM_PROCESSOR STREQUAL arm)
|
||||
set(ARM_LINKER_FLAGS "-Wl,--fix-cortex-a8 -Wl,--no-undefined -Wl,--gc-sections -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now")
|
||||
elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL aarch64)
|
||||
set(ARM_LINKER_FLAGS "-Wl,--no-undefined -Wl,--gc-sections -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now")
|
||||
endif()
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${ARM_LINKER_FLAGS} ${CMAKE_SHARED_LINKER_FLAGS}")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS "${ARM_LINKER_FLAGS} ${CMAKE_MODULE_LINKER_FLAGS}")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${ARM_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS}")
|
||||
else()
|
||||
#message(WARNING "CMAKE_CXX_FLAGS='${CMAKE_CXX_FLAGS}' is defined")
|
||||
endif()
|
||||
|
||||
if(USE_NEON)
|
||||
message(WARNING "You use obsolete variable USE_NEON to enable NEON instruction set. Use -DENABLE_NEON=ON instead." )
|
||||
set(ENABLE_NEON TRUE)
|
||||
elseif(USE_VFPV3)
|
||||
message(WARNING "You use obsolete variable USE_VFPV3 to enable VFPV3 instruction set. Use -DENABLE_VFPV3=ON instead." )
|
||||
set(ENABLE_VFPV3 TRUE)
|
||||
endif()
|
||||
|
||||
set(CMAKE_FIND_ROOT_PATH ${CMAKE_FIND_ROOT_PATH} ${ARM_LINUX_SYSROOT})
|
||||
|
||||
if(EXISTS ${CUDA_TOOLKIT_ROOT_DIR})
|
||||
set(CMAKE_FIND_ROOT_PATH ${CMAKE_FIND_ROOT_PATH} ${CUDA_TOOLKIT_ROOT_DIR})
|
||||
endif()
|
||||
|
||||
set(TOOLCHAIN_CONFIG_VARS ${TOOLCHAIN_CONFIG_VARS}
|
||||
ARM_LINUX_SYSROOT
|
||||
ENABLE_NEON
|
||||
ENABLE_VFPV3
|
||||
CUDA_TOOLKIT_ROOT_DIR
|
||||
)
|
||||
toolchain_save_config()
|
||||
97
cmake/toolchains/arm.toolchain.cmake
Normal file
97
cmake/toolchains/arm.toolchain.cmake
Normal file
@@ -0,0 +1,97 @@
|
||||
if(COMMAND toolchain_save_config)
|
||||
return() # prevent recursive call
|
||||
endif()
|
||||
|
||||
set(CMAKE_SYSTEM_NAME Linux)
|
||||
set(CMAKE_SYSTEM_VERSION 1)
|
||||
if(NOT DEFINED CMAKE_SYSTEM_PROCESSOR)
|
||||
set(CMAKE_SYSTEM_PROCESSOR arm)
|
||||
else()
|
||||
#message("CMAKE_SYSTEM_PROCESSOR=${CMAKE_SYSTEM_PROCESSOR}")
|
||||
endif()
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/gnu.toolchain.cmake")
|
||||
|
||||
if(CMAKE_SYSTEM_PROCESSOR STREQUAL arm AND NOT ARM_IGNORE_FP)
|
||||
set(FLOAT_ABI_SUFFIX "")
|
||||
if(NOT SOFTFP)
|
||||
set(FLOAT_ABI_SUFFIX "hf")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT "x${GCC_COMPILER_VERSION}" STREQUAL "x")
|
||||
set(__GCC_VER_SUFFIX "-${GCC_COMPILER_VERSION}")
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED CMAKE_C_COMPILER)
|
||||
find_program(CMAKE_C_COMPILER NAMES ${GNU_MACHINE}${FLOAT_ABI_SUFFIX}-gcc${__GCC_VER_SUFFIX})
|
||||
else()
|
||||
#message(WARNING "CMAKE_C_COMPILER=${CMAKE_C_COMPILER} is defined")
|
||||
endif()
|
||||
if(NOT DEFINED CMAKE_CXX_COMPILER)
|
||||
find_program(CMAKE_CXX_COMPILER NAMES ${GNU_MACHINE}${FLOAT_ABI_SUFFIX}-g++${__GCC_VER_SUFFIX})
|
||||
else()
|
||||
#message(WARNING "CMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} is defined")
|
||||
endif()
|
||||
if(NOT DEFINED CMAKE_LINKER)
|
||||
find_program(CMAKE_LINKER NAMES ${GNU_MACHINE}${FLOAT_ABI_SUFFIX}-ld${__GCC_VER_SUFFIX} ${GNU_MACHINE}${FLOAT_ABI_SUFFIX}-ld)
|
||||
else()
|
||||
#message(WARNING "CMAKE_LINKER=${CMAKE_LINKER} is defined")
|
||||
endif()
|
||||
if(NOT DEFINED CMAKE_AR)
|
||||
find_program(CMAKE_AR NAMES ${GNU_MACHINE}${FLOAT_ABI_SUFFIX}-ar${__GCC_VER_SUFFIX} ${GNU_MACHINE}${FLOAT_ABI_SUFFIX}-ar)
|
||||
else()
|
||||
#message(WARNING "CMAKE_AR=${CMAKE_AR} is defined")
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED ARM_LINUX_SYSROOT AND DEFINED GNU_MACHINE)
|
||||
set(ARM_LINUX_SYSROOT /usr/${GNU_MACHINE}${FLOAT_ABI_SUFFIX})
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED CMAKE_CXX_FLAGS)
|
||||
set(CMAKE_CXX_FLAGS "" CACHE INTERNAL "")
|
||||
set(CMAKE_C_FLAGS "" CACHE INTERNAL "")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "" CACHE INTERNAL "")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS "" CACHE INTERNAL "")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "" CACHE INTERNAL "")
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdata-sections -Wa,--noexecstack -fsigned-char -Wno-psabi")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fdata-sections -Wa,--noexecstack -fsigned-char -Wno-psabi")
|
||||
if(CMAKE_SYSTEM_PROCESSOR STREQUAL arm)
|
||||
set(CMAKE_CXX_FLAGS "-mthumb ${CMAKE_CXX_FLAGS}")
|
||||
set(CMAKE_C_FLAGS "-mthumb ${CMAKE_C_FLAGS}")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-z,nocopyreloc")
|
||||
endif()
|
||||
if(CMAKE_SYSTEM_PROCESSOR STREQUAL arm)
|
||||
set(ARM_LINKER_FLAGS "-Wl,--fix-cortex-a8 -Wl,--no-undefined -Wl,--gc-sections -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now")
|
||||
elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL aarch64)
|
||||
set(ARM_LINKER_FLAGS "-Wl,--no-undefined -Wl,--gc-sections -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now")
|
||||
endif()
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${ARM_LINKER_FLAGS} ${CMAKE_SHARED_LINKER_FLAGS}")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS "${ARM_LINKER_FLAGS} ${CMAKE_MODULE_LINKER_FLAGS}")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${ARM_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS}")
|
||||
else()
|
||||
#message(WARNING "CMAKE_CXX_FLAGS='${CMAKE_CXX_FLAGS}' is defined")
|
||||
endif()
|
||||
|
||||
if(USE_NEON)
|
||||
message(WARNING "You use obsolete variable USE_NEON to enable NEON instruction set. Use -DENABLE_NEON=ON instead." )
|
||||
set(ENABLE_NEON TRUE)
|
||||
elseif(USE_VFPV3)
|
||||
message(WARNING "You use obsolete variable USE_VFPV3 to enable VFPV3 instruction set. Use -DENABLE_VFPV3=ON instead." )
|
||||
set(ENABLE_VFPV3 TRUE)
|
||||
endif()
|
||||
|
||||
set(CMAKE_FIND_ROOT_PATH ${CMAKE_FIND_ROOT_PATH} ${ARM_LINUX_SYSROOT})
|
||||
|
||||
if(EXISTS ${CUDA_TOOLKIT_ROOT_DIR})
|
||||
set(CMAKE_FIND_ROOT_PATH ${CMAKE_FIND_ROOT_PATH} ${CUDA_TOOLKIT_ROOT_DIR})
|
||||
endif()
|
||||
|
||||
set(TOOLCHAIN_CONFIG_VARS ${TOOLCHAIN_CONFIG_VARS}
|
||||
ARM_LINUX_SYSROOT
|
||||
ENABLE_NEON
|
||||
ENABLE_VFPV3
|
||||
CUDA_TOOLKIT_ROOT_DIR
|
||||
)
|
||||
toolchain_save_config()
|
||||
134
cmake/toolchains/gnu.toolchain.cmake
Normal file
134
cmake/toolchains/gnu.toolchain.cmake
Normal file
@@ -0,0 +1,134 @@
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
# load settings in case of "try compile"
|
||||
set(TOOLCHAIN_CONFIG_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/toolchain.config.cmake")
|
||||
get_property(__IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE)
|
||||
if(__IN_TRY_COMPILE)
|
||||
include("${CMAKE_CURRENT_SOURCE_DIR}/../toolchain.config.cmake" OPTIONAL) # CMAKE_BINARY_DIR is different
|
||||
macro(toolchain_save_config)
|
||||
# nothing
|
||||
endmacro()
|
||||
else()
|
||||
macro(toolchain_save_config)
|
||||
set(__config "#message(\"Load TOOLCHAIN config...\")\n")
|
||||
get_cmake_property(__variableNames VARIABLES)
|
||||
set(__vars_list ${ARGN})
|
||||
list(APPEND __vars_list
|
||||
${TOOLCHAIN_CONFIG_VARS}
|
||||
CMAKE_SYSTEM_NAME
|
||||
CMAKE_SYSTEM_VERSION
|
||||
CMAKE_SYSTEM_PROCESSOR
|
||||
CMAKE_C_COMPILER
|
||||
CMAKE_CXX_COMPILER
|
||||
CMAKE_C_FLAGS
|
||||
CMAKE_CXX_FLAGS
|
||||
CMAKE_SHARED_LINKER_FLAGS
|
||||
CMAKE_MODULE_LINKER_FLAGS
|
||||
CMAKE_EXE_LINKER_FLAGS
|
||||
CMAKE_SKIP_RPATH
|
||||
CMAKE_FIND_ROOT_PATH
|
||||
GCC_COMPILER_VERSION
|
||||
)
|
||||
foreach(__var ${__variableNames})
|
||||
foreach(_v ${__vars_list})
|
||||
if("x${__var}" STREQUAL "x${_v}")
|
||||
if(${__var} MATCHES " ")
|
||||
set(__config "${__config}set(${__var} \"${${__var}}\")\n")
|
||||
else()
|
||||
set(__config "${__config}set(${__var} ${${__var}})\n")
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
endforeach()
|
||||
if(EXISTS "${TOOLCHAIN_CONFIG_FILE}")
|
||||
file(READ "${TOOLCHAIN_CONFIG_FILE}" __config_old)
|
||||
endif()
|
||||
if("${__config_old}" STREQUAL "${__config}")
|
||||
# nothing
|
||||
else()
|
||||
#message("Update TOOLCHAIN config: ${__config}")
|
||||
file(WRITE "${TOOLCHAIN_CONFIG_FILE}" "${__config}")
|
||||
endif()
|
||||
unset(__config)
|
||||
unset(__config_old)
|
||||
unset(__vars_list)
|
||||
unset(__variableNames)
|
||||
endmacro()
|
||||
endif() # IN_TRY_COMPILE
|
||||
|
||||
if(NOT CMAKE_FIND_ROOT_PATH_MODE_LIBRARY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
endif()
|
||||
|
||||
if(NOT CMAKE_FIND_ROOT_PATH_MODE_INCLUDE)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
endif()
|
||||
|
||||
if(NOT CMAKE_FIND_ROOT_PATH_MODE_PACKAGE)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
|
||||
endif()
|
||||
|
||||
if(NOT CMAKE_FIND_ROOT_PATH_MODE_PROGRAM)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
endif()
|
||||
|
||||
macro(__cmake_find_root_save_and_reset)
|
||||
foreach(v
|
||||
CMAKE_FIND_ROOT_PATH_MODE_LIBRARY
|
||||
CMAKE_FIND_ROOT_PATH_MODE_INCLUDE
|
||||
CMAKE_FIND_ROOT_PATH_MODE_PACKAGE
|
||||
CMAKE_FIND_ROOT_PATH_MODE_PROGRAM
|
||||
)
|
||||
set(__save_${v} ${${v}})
|
||||
set(${v} NEVER)
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
macro(__cmake_find_root_restore)
|
||||
foreach(v
|
||||
CMAKE_FIND_ROOT_PATH_MODE_LIBRARY
|
||||
CMAKE_FIND_ROOT_PATH_MODE_INCLUDE
|
||||
CMAKE_FIND_ROOT_PATH_MODE_PACKAGE
|
||||
CMAKE_FIND_ROOT_PATH_MODE_PROGRAM
|
||||
)
|
||||
set(${v} ${__save_${v}})
|
||||
unset(__save_${v})
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
|
||||
# macro to find programs on the host OS
|
||||
macro(find_host_program)
|
||||
__cmake_find_root_save_and_reset()
|
||||
if(CMAKE_HOST_WIN32)
|
||||
SET(WIN32 1)
|
||||
SET(UNIX)
|
||||
elseif(CMAKE_HOST_APPLE)
|
||||
SET(APPLE 1)
|
||||
SET(UNIX)
|
||||
endif()
|
||||
find_program(${ARGN})
|
||||
SET(WIN32)
|
||||
SET(APPLE)
|
||||
SET(UNIX 1)
|
||||
__cmake_find_root_restore()
|
||||
endmacro()
|
||||
|
||||
# macro to find packages on the host OS
|
||||
macro(find_host_package)
|
||||
__cmake_find_root_save_and_reset()
|
||||
if(CMAKE_HOST_WIN32)
|
||||
SET(WIN32 1)
|
||||
SET(UNIX)
|
||||
elseif(CMAKE_HOST_APPLE)
|
||||
SET(APPLE 1)
|
||||
SET(UNIX)
|
||||
endif()
|
||||
find_package(${ARGN})
|
||||
SET(WIN32)
|
||||
SET(APPLE)
|
||||
SET(UNIX 1)
|
||||
__cmake_find_root_restore()
|
||||
endmacro()
|
||||
|
||||
set(CMAKE_SKIP_RPATH TRUE CACHE BOOL "If set, runtime paths are not added when using shared libraries.")
|
||||
@@ -1,6 +1,8 @@
|
||||
project(cscore)
|
||||
|
||||
include(SubDirList)
|
||||
include(CompileWarnings)
|
||||
include(AddTest)
|
||||
|
||||
find_package( OpenCV REQUIRED )
|
||||
|
||||
@@ -21,14 +23,15 @@ if(NOT MSVC)
|
||||
endif()
|
||||
else()
|
||||
target_sources(cscore PRIVATE ${cscore_windows_src})
|
||||
target_compile_options(cscore PUBLIC -DNOMINMAX)
|
||||
target_compile_options(cscore PRIVATE -D_CRT_SECURE_NO_WARNINGS)
|
||||
target_compile_definitions(cscore PUBLIC -DNOMINMAX)
|
||||
target_compile_definitions(cscore PRIVATE -D_CRT_SECURE_NO_WARNINGS)
|
||||
endif()
|
||||
|
||||
target_include_directories(cscore PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/main/native/include>
|
||||
$<INSTALL_INTERFACE:${include_dest}/cscore>)
|
||||
target_include_directories(cscore PRIVATE src/main/native/cpp)
|
||||
wpilib_target_warnings(cscore)
|
||||
target_link_libraries(cscore PUBLIC wpiutil ${OpenCV_LIBS})
|
||||
|
||||
set_property(TARGET cscore PROPERTY FOLDER "libraries")
|
||||
@@ -36,13 +39,14 @@ set_property(TARGET cscore PROPERTY FOLDER "libraries")
|
||||
install(TARGETS cscore EXPORT cscore DESTINATION "${main_lib_dest}")
|
||||
install(DIRECTORY src/main/native/include/ DESTINATION "${include_dest}/cscore")
|
||||
|
||||
if (MSVC)
|
||||
if (MSVC OR FLAT_INSTALL_WPILIB)
|
||||
set (cscore_config_dir ${wpilib_dest})
|
||||
else()
|
||||
set (cscore_config_dir share/cscore)
|
||||
endif()
|
||||
|
||||
install(FILES cscore-config.cmake DESTINATION ${cscore_config_dir})
|
||||
configure_file(cscore-config.cmake.in ${CMAKE_BINARY_DIR}/cscore-config.cmake )
|
||||
install(FILES ${CMAKE_BINARY_DIR}/cscore-config.cmake DESTINATION ${cscore_config_dir})
|
||||
install(EXPORT cscore DESTINATION ${cscore_config_dir})
|
||||
|
||||
SUBDIR_LIST(cscore_examples "${CMAKE_CURRENT_SOURCE_DIR}/examples")
|
||||
@@ -50,7 +54,9 @@ foreach(example ${cscore_examples})
|
||||
file(GLOB cscore_example_src examples/${example}/*.cpp)
|
||||
if(cscore_example_src)
|
||||
add_executable(cscore_${example} ${cscore_example_src})
|
||||
wpilib_target_warnings(cscore_${example})
|
||||
target_link_libraries(cscore_${example} cscore)
|
||||
set_property(TARGET cscore_${example} PROPERTY FOLDER "examples")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
@@ -63,7 +69,9 @@ if (NOT WITHOUT_JAVA)
|
||||
|
||||
#find java files, copy them locally
|
||||
|
||||
set(OPENCV_JAVA_INSTALL_DIR ${OpenCV_INSTALL_PATH}/share/OpenCV/java/)
|
||||
if("${OPENCV_JAVA_INSTALL_DIR}" STREQUAL "")
|
||||
set(OPENCV_JAVA_INSTALL_DIR ${OpenCV_INSTALL_PATH}/share/OpenCV/java/)
|
||||
endif()
|
||||
|
||||
find_file(OPENCV_JAR_FILE NAMES opencv-${OpenCV_VERSION_MAJOR}${OpenCV_VERSION_MINOR}${OpenCV_VERSION_PATCH}.jar PATHS ${OPENCV_JAVA_INSTALL_DIR} ${OpenCV_INSTALL_PATH}/bin NO_DEFAULT_PATH)
|
||||
find_file(OPENCV_JNI_FILE NAMES libopencv_java${OpenCV_VERSION_MAJOR}${OpenCV_VERSION_MINOR}${OpenCV_VERSION_PATCH}.so
|
||||
@@ -101,6 +109,7 @@ if (NOT WITHOUT_JAVA)
|
||||
set_property(TARGET cscore_jar PROPERTY FOLDER "java")
|
||||
|
||||
add_library(cscorejni ${cscore_jni_src})
|
||||
wpilib_target_warnings(cscorejni)
|
||||
target_link_libraries(cscorejni PUBLIC cscore wpiutil ${OpenCV_LIBS})
|
||||
|
||||
set_property(TARGET cscorejni PROPERTY FOLDER "libraries")
|
||||
@@ -120,3 +129,8 @@ if (NOT WITHOUT_JAVA)
|
||||
install(TARGETS cscorejni EXPORT cscorejni DESTINATION "${main_lib_dest}")
|
||||
|
||||
endif()
|
||||
|
||||
if (WITH_TESTS)
|
||||
wpilib_add_test(cscore src/test/native/cpp)
|
||||
target_link_libraries(cscore_test cscore gmock)
|
||||
endif()
|
||||
|
||||
@@ -5,9 +5,13 @@ ext {
|
||||
devMain = 'edu.wpi.cscore.DevMain'
|
||||
}
|
||||
|
||||
if (OperatingSystem.current().isMacOsX()) {
|
||||
apply plugin: 'objective-cpp'
|
||||
}
|
||||
// Removed because having the objective-cpp plugin added breaks
|
||||
// embedded tools and its toolchain check. It causes an obj-cpp
|
||||
// source set to be added to all binaries, even cross binaries
|
||||
// with no support.
|
||||
// if (OperatingSystem.current().isMacOsX()) {
|
||||
// apply plugin: 'objective-cpp'
|
||||
// }
|
||||
|
||||
apply from: "${rootDir}/shared/jni/setupBuild.gradle"
|
||||
|
||||
@@ -15,23 +19,24 @@ ext {
|
||||
sharedCvConfigs = [cscore : [],
|
||||
cscoreBase: [],
|
||||
cscoreDev : [],
|
||||
cscoreTest: []]
|
||||
cscoreTest: [],
|
||||
cscoreJNIShared: []]
|
||||
staticCvConfigs = [cscoreJNI: []]
|
||||
useJava = true
|
||||
useCpp = true
|
||||
splitSetup = {
|
||||
if (it.targetPlatform.operatingSystem.name == 'osx') {
|
||||
if (it.targetPlatform.operatingSystem.isMacOsX()) {
|
||||
it.sources {
|
||||
macObjCpp(ObjectiveCppSourceSet) {
|
||||
source {
|
||||
srcDirs = ['src/main/native/objcpp']
|
||||
include '**/*.mm'
|
||||
}
|
||||
exportedHeaders {
|
||||
srcDirs 'src/main/native/include'
|
||||
include '**/*.h'
|
||||
}
|
||||
}
|
||||
// macObjCpp(ObjectiveCppSourceSet) {
|
||||
// source {
|
||||
// srcDirs = ['src/main/native/objcpp']
|
||||
// include '**/*.mm'
|
||||
// }
|
||||
// exportedHeaders {
|
||||
// srcDirs 'src/main/native/include'
|
||||
// include '**/*.h'
|
||||
// }
|
||||
// }
|
||||
cscoreMacCpp(CppSourceSet) {
|
||||
source {
|
||||
srcDirs 'src/main/native/osx'
|
||||
@@ -43,7 +48,7 @@ ext {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (it.targetPlatform.operatingSystem.name == 'linux') {
|
||||
} else if (it.targetPlatform.operatingSystem.isLinux()) {
|
||||
it.sources {
|
||||
cscoreLinuxCpp(CppSourceSet) {
|
||||
source {
|
||||
@@ -56,7 +61,7 @@ ext {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (it.targetPlatform.operatingSystem.name == 'windows') {
|
||||
} else if (it.targetPlatform.operatingSystem.isWindows()) {
|
||||
it.sources {
|
||||
cscoreWindowsCpp(CppSourceSet) {
|
||||
source {
|
||||
@@ -88,43 +93,28 @@ examplesTree.list(new FilenameFilter() {
|
||||
|
||||
apply from: "${rootDir}/shared/opencv.gradle"
|
||||
|
||||
model {
|
||||
// Exports config is a utility to enable exporting all symbols in a C++ library on windows to a DLL.
|
||||
// This removes the need for DllExport on a library. However, the gradle C++ builder has a bug
|
||||
// where some extra symbols are added that cannot be resolved at link time. This configuration
|
||||
// lets you specify specific symbols to exlude from exporting.
|
||||
exportsConfigs {
|
||||
cscore(ExportsConfig) {
|
||||
x86ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure',
|
||||
'_CT??_R0?AVbad_cast',
|
||||
'_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure',
|
||||
'_TI5?AVfailure', '==']
|
||||
x64ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure',
|
||||
'_CT??_R0?AVbad_cast',
|
||||
'_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure',
|
||||
'_TI5?AVfailure', '==']
|
||||
nativeUtils.exportsConfigs {
|
||||
cscore {
|
||||
x86ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure',
|
||||
'_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure',
|
||||
'_TI5?AVfailure', '_CT??_R0?AVout_of_range', '_CTA3?AVout_of_range',
|
||||
'_TI3?AVout_of_range', '_CT??_R0?AVbad_cast']
|
||||
x64ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure',
|
||||
'_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure',
|
||||
'_TI5?AVfailure', '_CT??_R0?AVout_of_range', '_CTA3?AVout_of_range',
|
||||
'_TI3?AVout_of_range', '_CT??_R0?AVbad_cast']
|
||||
}
|
||||
cscoreJNI {
|
||||
x86SymbolFilter = { symbols ->
|
||||
symbols.removeIf({ !it.startsWith('CS_') })
|
||||
}
|
||||
cscoreJNI(ExportsConfig) {
|
||||
x86SymbolFilter = { symbols ->
|
||||
def retList = []
|
||||
symbols.each { symbol ->
|
||||
if (symbol.startsWith('CS_')) {
|
||||
retList << symbol
|
||||
}
|
||||
}
|
||||
return retList
|
||||
}
|
||||
x64SymbolFilter = { symbols ->
|
||||
def retList = []
|
||||
symbols.each { symbol ->
|
||||
if (symbol.startsWith('CS_')) {
|
||||
retList << symbol
|
||||
}
|
||||
}
|
||||
return retList
|
||||
}
|
||||
x64SymbolFilter = { symbols ->
|
||||
symbols.removeIf({ !it.startsWith('CS_') })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
model {
|
||||
components {
|
||||
examplesMap.each { key, value ->
|
||||
"${key}"(NativeExecutableSpec) {
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
include(CMakeFindDependencyMacro)
|
||||
find_dependency(wpiutil)
|
||||
find_dependency(OpenCV)
|
||||
|
||||
get_filename_component(SELF_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
|
||||
include(${SELF_DIR}/cscore.cmake)
|
||||
6
cscore/cscore-config.cmake.in
Normal file
6
cscore/cscore-config.cmake.in
Normal file
@@ -0,0 +1,6 @@
|
||||
include(CMakeFindDependencyMacro)
|
||||
@FILENAME_DEP_REPLACE@
|
||||
@WPIUTIL_DEP_REPLACE@
|
||||
find_dependency(OpenCV)
|
||||
|
||||
include(${SELF_DIR}/cscore.cmake)
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2017-2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2017-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <opencv2/core/core.hpp>
|
||||
|
||||
#include "cscore.h"
|
||||
#include "cscore_cv.h"
|
||||
|
||||
int main() {
|
||||
cs::HttpCamera camera{"httpcam", "http://localhost:8081/?action=stream"};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2017-2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2017-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <opencv2/core/core.hpp>
|
||||
|
||||
#include "cscore.h"
|
||||
#include "cscore_cv.h"
|
||||
|
||||
int main() {
|
||||
cs::UsbCamera camera{"usbcam", 0};
|
||||
|
||||
96
cscore/java-examples/RawCVMatSink.java
Normal file
96
cscore/java-examples/RawCVMatSink.java
Normal file
@@ -0,0 +1,96 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
package edu.wpi.cscore;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.opencv.core.CvType;
|
||||
import org.opencv.core.Mat;
|
||||
|
||||
import edu.wpi.cscore.VideoMode.PixelFormat;
|
||||
import edu.wpi.cscore.raw.RawFrame;
|
||||
|
||||
public class RawCVMatSink extends ImageSink {
|
||||
RawFrame frame = new RawFrame();
|
||||
Mat tmpMat;
|
||||
ByteBuffer origByteBuffer;
|
||||
int width;
|
||||
int height;
|
||||
int pixelFormat;
|
||||
int bgrValue = PixelFormat.kBGR.getValue();
|
||||
|
||||
private int getCVFormat(PixelFormat pixelFormat) {
|
||||
int type = 0;
|
||||
switch (pixelFormat) {
|
||||
case kYUYV:
|
||||
case kRGB565:
|
||||
type = CvType.CV_8UC2;
|
||||
break;
|
||||
case kBGR:
|
||||
type = CvType.CV_8UC3;
|
||||
break;
|
||||
case kGray:
|
||||
case kMJPEG:
|
||||
default:
|
||||
type = CvType.CV_8UC1;
|
||||
break;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a sink for accepting OpenCV images.
|
||||
* WaitForFrame() must be called on the created sink to get each new
|
||||
* image.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
*/
|
||||
public RawCVMatSink(String name) {
|
||||
super(CameraServerJNI.createRawSink(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for the next frame and get the image.
|
||||
* Times out (returning 0) after 0.225 seconds.
|
||||
* The provided image will have three 3-bit channels stored in BGR order.
|
||||
*
|
||||
* @return Frame time, or 0 on error (call GetError() to obtain the error
|
||||
* message)
|
||||
*/
|
||||
public long grabFrame(Mat image) {
|
||||
return grabFrame(image, 0.225);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for the next frame and get the image.
|
||||
* Times out (returning 0) after timeout seconds.
|
||||
* The provided image will have three 3-bit channels stored in BGR order.
|
||||
*
|
||||
* @return Frame time, or 0 on error (call GetError() to obtain the error
|
||||
* message); the frame time is in 1 us increments.
|
||||
*/
|
||||
public long grabFrame(Mat image, double timeout) {
|
||||
frame.setWidth(0);
|
||||
frame.setHeight(0);
|
||||
frame.setPixelFormat(bgrValue);
|
||||
long rv = CameraServerJNI.grabSinkFrameTimeout(m_handle, frame, timeout);
|
||||
if (rv <= 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (frame.getDataByteBuffer() != origByteBuffer || width != frame.getWidth() || height != frame.getHeight() || pixelFormat != frame.getPixelFormat()) {
|
||||
origByteBuffer = frame.getDataByteBuffer();
|
||||
height = frame.getHeight();
|
||||
width = frame.getWidth();
|
||||
pixelFormat = frame.getPixelFormat();
|
||||
tmpMat = new Mat(frame.getHeight(), frame.getWidth(), getCVFormat(VideoMode.getPixelFormatFromInt(pixelFormat)), origByteBuffer);
|
||||
}
|
||||
tmpMat.copyTo(image);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
59
cscore/java-examples/RawCVMatSource.java
Normal file
59
cscore/java-examples/RawCVMatSource.java
Normal file
@@ -0,0 +1,59 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
package edu.wpi.cscore;
|
||||
|
||||
import org.opencv.core.Mat;
|
||||
|
||||
import edu.wpi.cscore.VideoMode.PixelFormat;
|
||||
|
||||
public class RawCVMatSource extends ImageSource {
|
||||
/**
|
||||
* Create an OpenCV source.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
* @param mode Video mode being generated
|
||||
*/
|
||||
public RawCVMatSource(String name, VideoMode mode) {
|
||||
super(CameraServerJNI.createRawSource(name,
|
||||
mode.pixelFormat.getValue(),
|
||||
mode.width,
|
||||
mode.height,
|
||||
mode.fps));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an OpenCV source.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
* @param pixelFormat Pixel format
|
||||
* @param width width
|
||||
* @param height height
|
||||
* @param fps fps
|
||||
*/
|
||||
public RawCVMatSource(String name, VideoMode.PixelFormat pixelFormat, int width, int height, int fps) {
|
||||
super(CameraServerJNI.createRawSource(name, pixelFormat.getValue(), width, height, fps));
|
||||
}
|
||||
|
||||
/**
|
||||
* Put an OpenCV image and notify sinks.
|
||||
*
|
||||
* <p>Only 8-bit single-channel or 3-channel (with BGR channel order) images
|
||||
* are supported. If the format, depth or channel order is different, use
|
||||
* Mat.convertTo() and/or cvtColor() to convert it first.
|
||||
*
|
||||
* @param image OpenCV image
|
||||
*/
|
||||
public void putFrame(Mat image) {
|
||||
int channels = image.channels();
|
||||
if (channels != 1 && channels != 3) {
|
||||
throw new VideoException("Unsupported Image Type");
|
||||
}
|
||||
int imgType = channels == 1 ? PixelFormat.kGray.getValue() : PixelFormat.kBGR.getValue();
|
||||
CameraServerJNI.putRawSourceFrame(m_handle, image.dataAddr(), image.width(), image.height(), imgType, (int)image.total() * channels);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2017-2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2017-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2017-2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2017-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
|
||||
72
cscore/src/main/java/edu/wpi/cscore/CameraServerCvJNI.java
Normal file
72
cscore/src/main/java/edu/wpi/cscore/CameraServerCvJNI.java
Normal file
@@ -0,0 +1,72 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
package edu.wpi.cscore;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.opencv.core.Core;
|
||||
|
||||
import edu.wpi.first.wpiutil.RuntimeLoader;
|
||||
|
||||
public class CameraServerCvJNI {
|
||||
static boolean libraryLoaded = false;
|
||||
|
||||
static RuntimeLoader<Core> loader = null;
|
||||
|
||||
public static class Helper {
|
||||
private static AtomicBoolean extractOnStaticLoad = new AtomicBoolean(true);
|
||||
|
||||
public static boolean getExtractOnStaticLoad() {
|
||||
return extractOnStaticLoad.get();
|
||||
}
|
||||
|
||||
public static void setExtractOnStaticLoad(boolean load) {
|
||||
extractOnStaticLoad.set(load);
|
||||
}
|
||||
}
|
||||
|
||||
static {
|
||||
String opencvName = Core.NATIVE_LIBRARY_NAME;
|
||||
if (Helper.getExtractOnStaticLoad()) {
|
||||
try {
|
||||
CameraServerJNI.forceLoad();
|
||||
loader = new RuntimeLoader<>(opencvName, RuntimeLoader.getDefaultExtractionRoot(), Core.class);
|
||||
loader.loadLibraryHashed();
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
libraryLoaded = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Force load the library.
|
||||
*/
|
||||
public static synchronized void forceLoad() throws IOException {
|
||||
if (libraryLoaded) {
|
||||
return;
|
||||
}
|
||||
CameraServerJNI.forceLoad();
|
||||
loader = new RuntimeLoader<>(Core.NATIVE_LIBRARY_NAME, RuntimeLoader.getDefaultExtractionRoot(), Core.class);
|
||||
loader.loadLibrary();
|
||||
libraryLoaded = true;
|
||||
}
|
||||
|
||||
public static native int createCvSource(String name, int pixelFormat, int width, int height, int fps);
|
||||
|
||||
public static native void putSourceFrame(int source, long imageNativeObj);
|
||||
|
||||
public static native int createCvSink(String name);
|
||||
//public static native int createCvSinkCallback(String name,
|
||||
// void (*processFrame)(long time));
|
||||
|
||||
public static native long grabSinkFrame(int sink, long imageNativeObj);
|
||||
public static native long grabSinkFrameTimeout(int sink, long imageNativeObj, double timeout);
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
@@ -8,21 +8,32 @@
|
||||
package edu.wpi.cscore;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.opencv.core.Core;
|
||||
|
||||
import edu.wpi.cscore.raw.RawFrame;
|
||||
import edu.wpi.first.wpiutil.RuntimeLoader;
|
||||
|
||||
public class CameraServerJNI {
|
||||
static boolean libraryLoaded = false;
|
||||
static boolean cvLibraryLoaded = false;
|
||||
|
||||
static RuntimeLoader<CameraServerJNI> loader = null;
|
||||
static RuntimeLoader<Core> cvLoader = null;
|
||||
|
||||
public static class Helper {
|
||||
private static AtomicBoolean extractOnStaticLoad = new AtomicBoolean(true);
|
||||
|
||||
public static boolean getExtractOnStaticLoad() {
|
||||
return extractOnStaticLoad.get();
|
||||
}
|
||||
|
||||
public static void setExtractOnStaticLoad(boolean load) {
|
||||
extractOnStaticLoad.set(load);
|
||||
}
|
||||
}
|
||||
|
||||
static {
|
||||
if (!libraryLoaded) {
|
||||
if (Helper.getExtractOnStaticLoad()) {
|
||||
try {
|
||||
loader = new RuntimeLoader<>("cscorejni", RuntimeLoader.getDefaultExtractionRoot(), CameraServerJNI.class);
|
||||
loader.loadLibrary();
|
||||
@@ -32,21 +43,19 @@ public class CameraServerJNI {
|
||||
}
|
||||
libraryLoaded = true;
|
||||
}
|
||||
|
||||
String opencvName = Core.NATIVE_LIBRARY_NAME;
|
||||
if (!cvLibraryLoaded) {
|
||||
try {
|
||||
cvLoader = new RuntimeLoader<>(opencvName, RuntimeLoader.getDefaultExtractionRoot(), Core.class);
|
||||
cvLoader.loadLibraryHashed();
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
cvLibraryLoaded = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static void forceLoad() {}
|
||||
/**
|
||||
* Force load the library.
|
||||
*/
|
||||
public static synchronized void forceLoad() throws IOException {
|
||||
if (libraryLoaded) {
|
||||
return;
|
||||
}
|
||||
loader = new RuntimeLoader<>("cscorejni", RuntimeLoader.getDefaultExtractionRoot(), CameraServerJNI.class);
|
||||
loader.loadLibrary();
|
||||
libraryLoaded = true;
|
||||
}
|
||||
|
||||
//
|
||||
// Property Functions
|
||||
@@ -70,7 +79,7 @@ public class CameraServerJNI {
|
||||
public static native int createUsbCameraPath(String name, String path);
|
||||
public static native int createHttpCamera(String name, String url, int kind);
|
||||
public static native int createHttpCameraMulti(String name, String[] urls, int kind);
|
||||
public static native int createCvSource(String name, int pixelFormat, int width, int height, int fps);
|
||||
public static native int createRawSource(String name, int pixelFormat, int width, int height, int fps);
|
||||
|
||||
//
|
||||
// Source Functions
|
||||
@@ -122,9 +131,13 @@ public class CameraServerJNI {
|
||||
public static native String[] getHttpCameraUrls(int source);
|
||||
|
||||
//
|
||||
// OpenCV Source Functions
|
||||
// Image Source Functions
|
||||
//
|
||||
public static native void putSourceFrame(int source, long imageNativeObj);
|
||||
public static native void putRawSourceFrameBB(int source, ByteBuffer data, int width, int height, int pixelFormat, int totalData);
|
||||
public static native void putRawSourceFrame(int source, long data, int width, int height, int pixelFormat, int totalData);
|
||||
public static void putRawSourceFrame(int source, RawFrame raw) {
|
||||
putRawSourceFrame(source, raw.getDataPtr(), raw.getWidth(), raw.getHeight(), raw.getPixelFormat(), raw.getTotalData());
|
||||
}
|
||||
public static native void notifySourceError(int source, String msg);
|
||||
public static native void setSourceConnected(int source, boolean connected);
|
||||
public static native void setSourceDescription(int source, String description);
|
||||
@@ -135,9 +148,8 @@ public class CameraServerJNI {
|
||||
// Sink Creation Functions
|
||||
//
|
||||
public static native int createMjpegServer(String name, String listenAddress, int port);
|
||||
public static native int createCvSink(String name);
|
||||
//public static native int createCvSinkCallback(String name,
|
||||
// void (*processFrame)(long time));
|
||||
|
||||
public static native int createRawSink(String name);
|
||||
|
||||
//
|
||||
// Sink Functions
|
||||
@@ -162,11 +174,19 @@ public class CameraServerJNI {
|
||||
public static native int getMjpegServerPort(int sink);
|
||||
|
||||
//
|
||||
// OpenCV Sink Functions
|
||||
// Image Sink Functions
|
||||
//
|
||||
public static native void setSinkDescription(int sink, String description);
|
||||
public static native long grabSinkFrame(int sink, long imageNativeObj);
|
||||
public static native long grabSinkFrameTimeout(int sink, long imageNativeObj, double timeout);
|
||||
|
||||
private static native long grabRawSinkFrameImpl(int sink, RawFrame rawFrame, long rawFramePtr, ByteBuffer byteBuffer, int width, int height, int pixelFormat);
|
||||
private static native long grabRawSinkFrameTimeoutImpl(int sink, RawFrame rawFrame, long rawFramePtr, ByteBuffer byteBuffer, int width, int height, int pixelFormat, double timeout);
|
||||
|
||||
public static long grabSinkFrame(int sink, RawFrame rawFrame) {
|
||||
return grabRawSinkFrameImpl(sink, rawFrame, rawFrame.getFramePtr(), rawFrame.getDataByteBuffer(), rawFrame.getWidth(), rawFrame.getHeight(), rawFrame.getPixelFormat());
|
||||
}
|
||||
public static long grabSinkFrameTimeout(int sink, RawFrame rawFrame, double timeout) {
|
||||
return grabRawSinkFrameTimeoutImpl(sink, rawFrame, rawFrame.getFramePtr(), rawFrame.getDataByteBuffer(), rawFrame.getWidth(), rawFrame.getHeight(), rawFrame.getPixelFormat(), timeout);
|
||||
}
|
||||
public static native String getSinkError(int sink);
|
||||
public static native void setSinkEnabled(int sink, boolean enabled);
|
||||
|
||||
@@ -228,4 +248,8 @@ public class CameraServerJNI {
|
||||
public static native String getHostname();
|
||||
|
||||
public static native String[] getNetworkInterfaces();
|
||||
|
||||
public static native long allocateRawFrame();
|
||||
|
||||
public static native void freeRawFrame(long frame);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
@@ -11,8 +11,11 @@ import org.opencv.core.Mat;
|
||||
|
||||
/**
|
||||
* A sink for user code to accept video frames as OpenCV images.
|
||||
* These sinks require the WPILib OpenCV builds.
|
||||
* For an alternate OpenCV, see the documentation how to build your own
|
||||
* with RawSink.
|
||||
*/
|
||||
public class CvSink extends VideoSink {
|
||||
public class CvSink extends ImageSink {
|
||||
/**
|
||||
* Create a sink for accepting OpenCV images.
|
||||
* WaitForFrame() must be called on the created sink to get each new
|
||||
@@ -21,7 +24,7 @@ public class CvSink extends VideoSink {
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
*/
|
||||
public CvSink(String name) {
|
||||
super(CameraServerJNI.createCvSink(name));
|
||||
super(CameraServerCvJNI.createCvSink(name));
|
||||
}
|
||||
|
||||
/// Create a sink for accepting OpenCV images in a separate thread.
|
||||
@@ -37,15 +40,6 @@ public class CvSink extends VideoSink {
|
||||
// super(CameraServerJNI.createCvSinkCallback(name, processFrame));
|
||||
//}
|
||||
|
||||
/**
|
||||
* Set sink description.
|
||||
*
|
||||
* @param description Description
|
||||
*/
|
||||
public void setDescription(String description) {
|
||||
CameraServerJNI.setSinkDescription(m_handle, description);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for the next frame and get the image.
|
||||
* Times out (returning 0) after 0.225 seconds.
|
||||
@@ -67,7 +61,7 @@ public class CvSink extends VideoSink {
|
||||
* message); the frame time is in 1 us increments.
|
||||
*/
|
||||
public long grabFrame(Mat image, double timeout) {
|
||||
return CameraServerJNI.grabSinkFrameTimeout(m_handle, image.nativeObj, timeout);
|
||||
return CameraServerCvJNI.grabSinkFrameTimeout(m_handle, image.nativeObj, timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -78,24 +72,6 @@ public class CvSink extends VideoSink {
|
||||
* message); the frame time is in 1 us increments.
|
||||
*/
|
||||
public long grabFrameNoTimeout(Mat image) {
|
||||
return CameraServerJNI.grabSinkFrame(m_handle, image.nativeObj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get error string. Call this if WaitForFrame() returns 0 to determine
|
||||
* what the error is.
|
||||
*/
|
||||
public String getError() {
|
||||
return CameraServerJNI.getSinkError(m_handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable getting new frames.
|
||||
* Disabling will cause processFrame (for callback-based CvSinks) to not
|
||||
* be called and WaitForFrame() to not return. This can be used to save
|
||||
* processor resources when frames are not needed.
|
||||
*/
|
||||
public void setEnabled(boolean enabled) {
|
||||
CameraServerJNI.setSinkEnabled(m_handle, enabled);
|
||||
return CameraServerCvJNI.grabSinkFrame(m_handle, image.nativeObj);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
@@ -11,8 +11,11 @@ import org.opencv.core.Mat;
|
||||
|
||||
/**
|
||||
* A source that represents a video camera.
|
||||
* These sources require the WPILib OpenCV builds.
|
||||
* For an alternate OpenCV, see the documentation how to build your own
|
||||
* with RawSource.
|
||||
*/
|
||||
public class CvSource extends VideoSource {
|
||||
public class CvSource extends ImageSource {
|
||||
/**
|
||||
* Create an OpenCV source.
|
||||
*
|
||||
@@ -20,7 +23,7 @@ public class CvSource extends VideoSource {
|
||||
* @param mode Video mode being generated
|
||||
*/
|
||||
public CvSource(String name, VideoMode mode) {
|
||||
super(CameraServerJNI.createCvSource(name,
|
||||
super(CameraServerCvJNI.createCvSource(name,
|
||||
mode.pixelFormat.getValue(),
|
||||
mode.width,
|
||||
mode.height,
|
||||
@@ -37,7 +40,7 @@ public class CvSource extends VideoSource {
|
||||
* @param fps fps
|
||||
*/
|
||||
public CvSource(String name, VideoMode.PixelFormat pixelFormat, int width, int height, int fps) {
|
||||
super(CameraServerJNI.createCvSource(name, pixelFormat.getValue(), width, height, fps));
|
||||
super(CameraServerCvJNI.createCvSource(name, pixelFormat.getValue(), width, height, fps));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -50,154 +53,7 @@ public class CvSource extends VideoSource {
|
||||
* @param image OpenCV image
|
||||
*/
|
||||
public void putFrame(Mat image) {
|
||||
CameraServerJNI.putSourceFrame(m_handle, image.nativeObj);
|
||||
CameraServerCvJNI.putSourceFrame(m_handle, image.nativeObj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Signal sinks that an error has occurred. This should be called instead
|
||||
* of NotifyFrame when an error occurs.
|
||||
*/
|
||||
public void notifyError(String msg) {
|
||||
CameraServerJNI.notifySourceError(m_handle, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set source connection status. Defaults to true.
|
||||
*
|
||||
* @param connected True for connected, false for disconnected
|
||||
*/
|
||||
public void setConnected(boolean connected) {
|
||||
CameraServerJNI.setSourceConnected(m_handle, connected);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set source description.
|
||||
*
|
||||
* @param description Description
|
||||
*/
|
||||
public void setDescription(String description) {
|
||||
CameraServerJNI.setSourceDescription(m_handle, description);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a property.
|
||||
*
|
||||
* @param name Property name
|
||||
* @param kind Property kind
|
||||
* @param minimum Minimum value
|
||||
* @param maximum Maximum value
|
||||
* @param step Step value
|
||||
* @param defaultValue Default value
|
||||
* @param value Current value
|
||||
* @return Property
|
||||
*/
|
||||
public VideoProperty createProperty(String name,
|
||||
VideoProperty.Kind kind,
|
||||
int minimum,
|
||||
int maximum,
|
||||
int step,
|
||||
int defaultValue,
|
||||
int value) {
|
||||
return new VideoProperty(
|
||||
CameraServerJNI.createSourceProperty(m_handle,
|
||||
name,
|
||||
kind.getValue(),
|
||||
minimum,
|
||||
maximum,
|
||||
step,
|
||||
defaultValue,
|
||||
value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an integer property.
|
||||
*
|
||||
* @param name Property name
|
||||
* @param minimum Minimum value
|
||||
* @param maximum Maximum value
|
||||
* @param step Step value
|
||||
* @param defaultValue Default value
|
||||
* @param value Current value
|
||||
* @return Property
|
||||
*/
|
||||
public VideoProperty createIntegerProperty(String name,
|
||||
int minimum,
|
||||
int maximum,
|
||||
int step,
|
||||
int defaultValue,
|
||||
int value) {
|
||||
return new VideoProperty(
|
||||
CameraServerJNI.createSourceProperty(m_handle,
|
||||
name,
|
||||
VideoProperty.Kind.kInteger.getValue(),
|
||||
minimum,
|
||||
maximum,
|
||||
step,
|
||||
defaultValue,
|
||||
value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a boolean property.
|
||||
*
|
||||
* @param name Property name
|
||||
* @param defaultValue Default value
|
||||
* @param value Current value
|
||||
* @return Property
|
||||
*/
|
||||
public VideoProperty createBooleanProperty(String name, boolean defaultValue, boolean value) {
|
||||
return new VideoProperty(
|
||||
CameraServerJNI.createSourceProperty(m_handle,
|
||||
name,
|
||||
VideoProperty.Kind.kBoolean.getValue(),
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
defaultValue ? 1 : 0,
|
||||
value ? 1 : 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a string property.
|
||||
*
|
||||
* @param name Property name
|
||||
* @param value Current value
|
||||
* @return Property
|
||||
*/
|
||||
public VideoProperty createStringProperty(String name, String value) {
|
||||
VideoProperty prop = new VideoProperty(
|
||||
CameraServerJNI.createSourceProperty(m_handle,
|
||||
name,
|
||||
VideoProperty.Kind.kString.getValue(),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0));
|
||||
prop.setString(value);
|
||||
return prop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure enum property choices.
|
||||
*
|
||||
* @param property Property
|
||||
* @param choices Choices
|
||||
*/
|
||||
public void setEnumPropertyChoices(VideoProperty property, String[] choices) {
|
||||
CameraServerJNI.setSourceEnumPropertyChoices(m_handle, property.m_handle, choices);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure enum property choices.
|
||||
*
|
||||
* @param property Property
|
||||
* @param choices Choices
|
||||
* @deprecated Use {@code setEnumPropertyChoices} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@SuppressWarnings("MethodName")
|
||||
public void SetEnumPropertyChoices(VideoProperty property, String[] choices) {
|
||||
setEnumPropertyChoices(property, choices);
|
||||
}
|
||||
}
|
||||
|
||||
41
cscore/src/main/java/edu/wpi/cscore/ImageSink.java
Normal file
41
cscore/src/main/java/edu/wpi/cscore/ImageSink.java
Normal file
@@ -0,0 +1,41 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
package edu.wpi.cscore;
|
||||
|
||||
public abstract class ImageSink extends VideoSink {
|
||||
protected ImageSink(int handle) {
|
||||
super(handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set sink description.
|
||||
*
|
||||
* @param description Description
|
||||
*/
|
||||
public void setDescription(String description) {
|
||||
CameraServerJNI.setSinkDescription(m_handle, description);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get error string. Call this if WaitForFrame() returns 0 to determine
|
||||
* what the error is.
|
||||
*/
|
||||
public String getError() {
|
||||
return CameraServerJNI.getSinkError(m_handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable getting new frames.
|
||||
* Disabling will cause processFrame (for callback-based CvSinks) to not
|
||||
* be called and WaitForFrame() to not return. This can be used to save
|
||||
* processor resources when frames are not needed.
|
||||
*/
|
||||
public void setEnabled(boolean enabled) {
|
||||
CameraServerJNI.setSinkEnabled(m_handle, enabled);
|
||||
}
|
||||
}
|
||||
162
cscore/src/main/java/edu/wpi/cscore/ImageSource.java
Normal file
162
cscore/src/main/java/edu/wpi/cscore/ImageSource.java
Normal file
@@ -0,0 +1,162 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
package edu.wpi.cscore;
|
||||
|
||||
public abstract class ImageSource extends VideoSource {
|
||||
protected ImageSource(int handle) {
|
||||
super(handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Signal sinks that an error has occurred. This should be called instead
|
||||
* of NotifyFrame when an error occurs.
|
||||
*/
|
||||
public void notifyError(String msg) {
|
||||
CameraServerJNI.notifySourceError(m_handle, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set source connection status. Defaults to true.
|
||||
*
|
||||
* @param connected True for connected, false for disconnected
|
||||
*/
|
||||
public void setConnected(boolean connected) {
|
||||
CameraServerJNI.setSourceConnected(m_handle, connected);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set source description.
|
||||
*
|
||||
* @param description Description
|
||||
*/
|
||||
public void setDescription(String description) {
|
||||
CameraServerJNI.setSourceDescription(m_handle, description);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a property.
|
||||
*
|
||||
* @param name Property name
|
||||
* @param kind Property kind
|
||||
* @param minimum Minimum value
|
||||
* @param maximum Maximum value
|
||||
* @param step Step value
|
||||
* @param defaultValue Default value
|
||||
* @param value Current value
|
||||
* @return Property
|
||||
*/
|
||||
public VideoProperty createProperty(String name,
|
||||
VideoProperty.Kind kind,
|
||||
int minimum,
|
||||
int maximum,
|
||||
int step,
|
||||
int defaultValue,
|
||||
int value) {
|
||||
return new VideoProperty(
|
||||
CameraServerJNI.createSourceProperty(m_handle,
|
||||
name,
|
||||
kind.getValue(),
|
||||
minimum,
|
||||
maximum,
|
||||
step,
|
||||
defaultValue,
|
||||
value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an integer property.
|
||||
*
|
||||
* @param name Property name
|
||||
* @param minimum Minimum value
|
||||
* @param maximum Maximum value
|
||||
* @param step Step value
|
||||
* @param defaultValue Default value
|
||||
* @param value Current value
|
||||
* @return Property
|
||||
*/
|
||||
public VideoProperty createIntegerProperty(String name,
|
||||
int minimum,
|
||||
int maximum,
|
||||
int step,
|
||||
int defaultValue,
|
||||
int value) {
|
||||
return new VideoProperty(
|
||||
CameraServerJNI.createSourceProperty(m_handle,
|
||||
name,
|
||||
VideoProperty.Kind.kInteger.getValue(),
|
||||
minimum,
|
||||
maximum,
|
||||
step,
|
||||
defaultValue,
|
||||
value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a boolean property.
|
||||
*
|
||||
* @param name Property name
|
||||
* @param defaultValue Default value
|
||||
* @param value Current value
|
||||
* @return Property
|
||||
*/
|
||||
public VideoProperty createBooleanProperty(String name, boolean defaultValue, boolean value) {
|
||||
return new VideoProperty(
|
||||
CameraServerJNI.createSourceProperty(m_handle,
|
||||
name,
|
||||
VideoProperty.Kind.kBoolean.getValue(),
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
defaultValue ? 1 : 0,
|
||||
value ? 1 : 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a string property.
|
||||
*
|
||||
* @param name Property name
|
||||
* @param value Current value
|
||||
* @return Property
|
||||
*/
|
||||
public VideoProperty createStringProperty(String name, String value) {
|
||||
VideoProperty prop = new VideoProperty(
|
||||
CameraServerJNI.createSourceProperty(m_handle,
|
||||
name,
|
||||
VideoProperty.Kind.kString.getValue(),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0));
|
||||
prop.setString(value);
|
||||
return prop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure enum property choices.
|
||||
*
|
||||
* @param property Property
|
||||
* @param choices Choices
|
||||
*/
|
||||
public void setEnumPropertyChoices(VideoProperty property, String[] choices) {
|
||||
CameraServerJNI.setSourceEnumPropertyChoices(m_handle, property.m_handle, choices);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure enum property choices.
|
||||
*
|
||||
* @param property Property
|
||||
* @param choices Choices
|
||||
* @deprecated Use {@code setEnumPropertyChoices} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@SuppressWarnings("MethodName")
|
||||
public void SetEnumPropertyChoices(VideoProperty property, String[] choices) {
|
||||
setEnumPropertyChoices(property, choices);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
@@ -18,13 +18,18 @@ public class UsbCameraInfo {
|
||||
* @param path Path to device if available (e.g. '/dev/video0' on Linux)
|
||||
* @param name Vendor/model name of the camera as provided by the USB driver
|
||||
* @param otherPaths Other path aliases to device
|
||||
* @param vendorId USB vendor id
|
||||
* @param productId USB product id
|
||||
*/
|
||||
@SuppressWarnings("PMD.ArrayIsStoredDirectly")
|
||||
public UsbCameraInfo(int dev, String path, String name, String[] otherPaths) {
|
||||
public UsbCameraInfo(int dev, String path, String name, String[] otherPaths, int vendorId,
|
||||
int productId) {
|
||||
this.dev = dev;
|
||||
this.path = path;
|
||||
this.name = name;
|
||||
this.otherPaths = otherPaths;
|
||||
this.vendorId = vendorId;
|
||||
this.productId = productId;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -50,4 +55,16 @@ public class UsbCameraInfo {
|
||||
*/
|
||||
@SuppressWarnings("MemberName")
|
||||
public String[] otherPaths;
|
||||
|
||||
/**
|
||||
* USB vendor id.
|
||||
*/
|
||||
@SuppressWarnings("MemberName")
|
||||
public int vendorId;
|
||||
|
||||
/**
|
||||
* USB product id.
|
||||
*/
|
||||
@SuppressWarnings("MemberName")
|
||||
public int productId;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
@@ -27,11 +27,6 @@ public class VideoListener implements AutoCloseable {
|
||||
m_handle = CameraServerJNI.addListener(listener, eventMask, immediateNotify);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void free() {
|
||||
close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void close() {
|
||||
if (m_handle != 0) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
@@ -14,7 +14,7 @@ package edu.wpi.cscore;
|
||||
*/
|
||||
public class VideoSink implements AutoCloseable {
|
||||
public enum Kind {
|
||||
kUnknown(0), kMjpeg(2), kCv(4);
|
||||
kUnknown(0), kMjpeg(2), kCv(4), kRaw(8);
|
||||
|
||||
@SuppressWarnings("MemberName")
|
||||
private final int value;
|
||||
@@ -46,11 +46,6 @@ public class VideoSink implements AutoCloseable {
|
||||
m_handle = handle;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void free() {
|
||||
close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void close() {
|
||||
if (m_handle != 0) {
|
||||
@@ -186,7 +181,7 @@ public class VideoSink implements AutoCloseable {
|
||||
* @return Connected source; nullptr if no source connected.
|
||||
*/
|
||||
public VideoSource getSource() {
|
||||
// While VideoSource.free() will call releaseSource(), getSinkSource()
|
||||
// While VideoSource.close() will call releaseSource(), getSinkSource()
|
||||
// increments the internal reference count so this is okay to do.
|
||||
return new VideoSource(CameraServerJNI.getSinkSource(m_handle));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
@@ -14,7 +14,7 @@ package edu.wpi.cscore;
|
||||
*/
|
||||
public class VideoSource implements AutoCloseable {
|
||||
public enum Kind {
|
||||
kUnknown(0), kUsb(1), kHttp(2), kCv(4);
|
||||
kUnknown(0), kUsb(1), kHttp(2), kCv(4), kRaw(8);
|
||||
|
||||
@SuppressWarnings("MemberName")
|
||||
private final int value;
|
||||
@@ -81,11 +81,6 @@ public class VideoSource implements AutoCloseable {
|
||||
m_handle = handle;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void free() {
|
||||
close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void close() {
|
||||
if (m_handle != 0) {
|
||||
|
||||
130
cscore/src/main/java/edu/wpi/cscore/raw/RawFrame.java
Normal file
130
cscore/src/main/java/edu/wpi/cscore/raw/RawFrame.java
Normal file
@@ -0,0 +1,130 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
package edu.wpi.cscore.raw;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import edu.wpi.cscore.CameraServerJNI;
|
||||
|
||||
/**
|
||||
* Class for storing raw frame data between image read call.
|
||||
*
|
||||
* <p>Data is reused for each frame read, rather then reallocating every frame.
|
||||
*/
|
||||
public class RawFrame implements AutoCloseable {
|
||||
private final long m_framePtr;
|
||||
private ByteBuffer m_dataByteBuffer;
|
||||
private long m_dataPtr;
|
||||
private int m_totalData;
|
||||
private int m_width;
|
||||
private int m_height;
|
||||
private int m_pixelFormat;
|
||||
|
||||
/**
|
||||
* Construct a new RawFrame.
|
||||
*/
|
||||
public RawFrame() {
|
||||
m_framePtr = CameraServerJNI.allocateRawFrame();
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the RawFrame, releasing native resources.
|
||||
* Any images currently using the data will be invalidated.
|
||||
*/
|
||||
@Override
|
||||
public void close() {
|
||||
CameraServerJNI.freeRawFrame(m_framePtr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from JNI to set data in class.
|
||||
*/
|
||||
public void setData(ByteBuffer dataByteBuffer, long dataPtr, int totalData,
|
||||
int width, int height, int pixelFormat) {
|
||||
m_dataByteBuffer = dataByteBuffer;
|
||||
m_dataPtr = dataPtr;
|
||||
m_totalData = totalData;
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
m_pixelFormat = pixelFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the pointer to native representation of this frame.
|
||||
*/
|
||||
public long getFramePtr() {
|
||||
return m_framePtr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a ByteBuffer pointing to the frame data.
|
||||
* This ByteBuffer is backed by the frame directly. Its lifetime is controlled by
|
||||
* the frame. If a new frame gets read, it will overwrite the current one.
|
||||
*/
|
||||
public ByteBuffer getDataByteBuffer() {
|
||||
return m_dataByteBuffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a long (is a char* in native code) pointing to the frame data.
|
||||
* This pointer is backed by the frame directly. Its lifetime is controlled by
|
||||
* the frame. If a new frame gets read, it will overwrite the current one.
|
||||
*/
|
||||
public long getDataPtr() {
|
||||
return m_dataPtr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the total length of the data stored in the frame.
|
||||
*/
|
||||
public int getTotalData() {
|
||||
return m_totalData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the width of the frame.
|
||||
*/
|
||||
public int getWidth() {
|
||||
return m_width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the width of the frame.
|
||||
*/
|
||||
public void setWidth(int width) {
|
||||
this.m_width = width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the height of the frame.
|
||||
*/
|
||||
public int getHeight() {
|
||||
return m_height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the height of the frame.
|
||||
*/
|
||||
public void setHeight(int height) {
|
||||
this.m_height = height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the PixelFormat of the frame.
|
||||
*/
|
||||
public int getPixelFormat() {
|
||||
return m_pixelFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the PixelFormat of the frame.
|
||||
*/
|
||||
public void setPixelFormat(int pixelFormat) {
|
||||
this.m_pixelFormat = pixelFormat;
|
||||
}
|
||||
}
|
||||
68
cscore/src/main/java/edu/wpi/cscore/raw/RawSink.java
Normal file
68
cscore/src/main/java/edu/wpi/cscore/raw/RawSink.java
Normal file
@@ -0,0 +1,68 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
package edu.wpi.cscore.raw;
|
||||
|
||||
import edu.wpi.cscore.CameraServerJNI;
|
||||
import edu.wpi.cscore.ImageSink;
|
||||
|
||||
/**
|
||||
* A sink for user code to accept video frames as raw bytes.
|
||||
*
|
||||
* <p>This is a complex API, most cases should use CvSink.
|
||||
*/
|
||||
public class RawSink extends ImageSink {
|
||||
/**
|
||||
* Create a sink for accepting raw images.
|
||||
*
|
||||
* <p>grabFrame() must be called on the created sink to get each new
|
||||
* image.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
*/
|
||||
public RawSink(String name) {
|
||||
super(CameraServerJNI.createRawSink(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for the next frame and get the image.
|
||||
* Times out (returning 0) after 0.225 seconds.
|
||||
* The provided image will have three 8-bit channels stored in BGR order.
|
||||
*
|
||||
* @return Frame time, or 0 on error (call getError() to obtain the error
|
||||
* message); the frame time is in the same time base as wpi::Now(),
|
||||
* and is in 1 us increments.
|
||||
*/
|
||||
protected long grabFrame(RawFrame frame) {
|
||||
return grabFrame(frame, 0.225);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for the next frame and get the image.
|
||||
* Times out (returning 0) after timeout seconds.
|
||||
* The provided image will have three 8-bit channels stored in BGR order.
|
||||
*
|
||||
* @return Frame time, or 0 on error (call getError() to obtain the error
|
||||
* message); the frame time is in the same time base as wpi::Now(),
|
||||
* and is in 1 us increments.
|
||||
*/
|
||||
protected long grabFrame(RawFrame frame, double timeout) {
|
||||
return CameraServerJNI.grabSinkFrameTimeout(m_handle, frame, timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for the next frame and get the image. May block forever.
|
||||
* The provided image will have three 8-bit channels stored in BGR order.
|
||||
*
|
||||
* @return Frame time, or 0 on error (call getError() to obtain the error
|
||||
* message); the frame time is in the same time base as wpi::Now(),
|
||||
* and is in 1 us increments.
|
||||
*/
|
||||
protected long grabFrameNoTimeout(RawFrame frame) {
|
||||
return CameraServerJNI.grabSinkFrame(m_handle, frame);
|
||||
}
|
||||
}
|
||||
85
cscore/src/main/java/edu/wpi/cscore/raw/RawSource.java
Normal file
85
cscore/src/main/java/edu/wpi/cscore/raw/RawSource.java
Normal file
@@ -0,0 +1,85 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
package edu.wpi.cscore.raw;
|
||||
|
||||
import edu.wpi.cscore.CameraServerJNI;
|
||||
import edu.wpi.cscore.ImageSource;
|
||||
import edu.wpi.cscore.VideoMode;
|
||||
|
||||
/**
|
||||
* A source for user code to provide video frames as raw bytes.
|
||||
*
|
||||
* <p>This is a complex API, most cases should use CvSource.
|
||||
*/
|
||||
public class RawSource extends ImageSource {
|
||||
/**
|
||||
* Create a raw frame source.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
* @param mode Video mode being generated
|
||||
*/
|
||||
public RawSource(String name, VideoMode mode) {
|
||||
super(CameraServerJNI.createRawSource(name,
|
||||
mode.pixelFormat.getValue(),
|
||||
mode.width, mode.height,
|
||||
mode.fps));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a raw frame source.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
* @param pixelFormat Pixel format
|
||||
* @param width width
|
||||
* @param height height
|
||||
* @param fps fps
|
||||
*/
|
||||
public RawSource(String name, VideoMode.PixelFormat pixelFormat, int width, int height, int fps) {
|
||||
super(CameraServerJNI.createRawSource(name,
|
||||
pixelFormat.getValue(),
|
||||
width, height,
|
||||
fps));
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a raw image and notify sinks.
|
||||
*
|
||||
* @param image raw frame image
|
||||
*/
|
||||
protected void putFrame(RawFrame image) {
|
||||
CameraServerJNI.putRawSourceFrame(m_handle, image);
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a raw image and notify sinks.
|
||||
*
|
||||
* @param data raw frame data pointer
|
||||
* @param width frame width
|
||||
* @param height frame height
|
||||
* @param pixelFormat pixel format
|
||||
* @param totalData length of data in total
|
||||
*/
|
||||
protected void putFrame(long data, int width, int height, int pixelFormat, int totalData) {
|
||||
CameraServerJNI.putRawSourceFrame(m_handle, data, width, height, pixelFormat, totalData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a raw image and notify sinks.
|
||||
*
|
||||
* @param data raw frame data pointer
|
||||
* @param width frame width
|
||||
* @param height frame height
|
||||
* @param pixelFormat pixel format
|
||||
* @param totalData length of data in total
|
||||
*/
|
||||
protected void putFrame(long data, int width, int height, VideoMode.PixelFormat pixelFormat,
|
||||
int totalData) {
|
||||
CameraServerJNI.putRawSourceFrame(m_handle, data, width, height, pixelFormat.getValue(),
|
||||
totalData);
|
||||
}
|
||||
}
|
||||
109
cscore/src/main/native/cpp/ConfigurableSourceImpl.cpp
Normal file
109
cscore/src/main/native/cpp/ConfigurableSourceImpl.cpp
Normal file
@@ -0,0 +1,109 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "ConfigurableSourceImpl.h"
|
||||
|
||||
#include <wpi/timestamp.h>
|
||||
|
||||
#include "Handle.h"
|
||||
#include "Instance.h"
|
||||
#include "Log.h"
|
||||
#include "Notifier.h"
|
||||
|
||||
using namespace cs;
|
||||
|
||||
ConfigurableSourceImpl::ConfigurableSourceImpl(const wpi::Twine& name,
|
||||
wpi::Logger& logger,
|
||||
Notifier& notifier,
|
||||
Telemetry& telemetry,
|
||||
const VideoMode& mode)
|
||||
: SourceImpl{name, logger, notifier, telemetry} {
|
||||
m_mode = mode;
|
||||
m_videoModes.push_back(m_mode);
|
||||
}
|
||||
|
||||
ConfigurableSourceImpl::~ConfigurableSourceImpl() {}
|
||||
|
||||
void ConfigurableSourceImpl::Start() {
|
||||
m_notifier.NotifySource(*this, CS_SOURCE_CONNECTED);
|
||||
m_notifier.NotifySource(*this, CS_SOURCE_VIDEOMODES_UPDATED);
|
||||
m_notifier.NotifySourceVideoMode(*this, m_mode);
|
||||
}
|
||||
|
||||
bool ConfigurableSourceImpl::SetVideoMode(const VideoMode& mode,
|
||||
CS_Status* status) {
|
||||
{
|
||||
std::scoped_lock lock(m_mutex);
|
||||
m_mode = mode;
|
||||
m_videoModes[0] = mode;
|
||||
}
|
||||
m_notifier.NotifySourceVideoMode(*this, mode);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ConfigurableSourceImpl::NumSinksChanged() {
|
||||
// ignore
|
||||
}
|
||||
|
||||
void ConfigurableSourceImpl::NumSinksEnabledChanged() {
|
||||
// ignore
|
||||
}
|
||||
|
||||
void ConfigurableSourceImpl::NotifyError(const wpi::Twine& msg) {
|
||||
PutError(msg, wpi::Now());
|
||||
}
|
||||
|
||||
int ConfigurableSourceImpl::CreateProperty(const wpi::Twine& name,
|
||||
CS_PropertyKind kind, int minimum,
|
||||
int maximum, int step,
|
||||
int defaultValue, int value) {
|
||||
std::scoped_lock lock(m_mutex);
|
||||
int ndx = CreateOrUpdateProperty(name,
|
||||
[=] {
|
||||
return std::make_unique<PropertyImpl>(
|
||||
name, kind, minimum, maximum, step,
|
||||
defaultValue, value);
|
||||
},
|
||||
[&](PropertyImpl& prop) {
|
||||
// update all but value
|
||||
prop.propKind = kind;
|
||||
prop.minimum = minimum;
|
||||
prop.maximum = maximum;
|
||||
prop.step = step;
|
||||
prop.defaultValue = defaultValue;
|
||||
value = prop.value;
|
||||
});
|
||||
m_notifier.NotifySourceProperty(*this, CS_SOURCE_PROPERTY_CREATED, name, ndx,
|
||||
kind, value, wpi::Twine{});
|
||||
return ndx;
|
||||
}
|
||||
|
||||
int ConfigurableSourceImpl::CreateProperty(
|
||||
const wpi::Twine& name, CS_PropertyKind kind, int minimum, int maximum,
|
||||
int step, int defaultValue, int value,
|
||||
std::function<void(CS_Property property)> onChange) {
|
||||
// TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ConfigurableSourceImpl::SetEnumPropertyChoices(
|
||||
int property, wpi::ArrayRef<std::string> choices, CS_Status* status) {
|
||||
std::scoped_lock lock(m_mutex);
|
||||
auto prop = GetProperty(property);
|
||||
if (!prop) {
|
||||
*status = CS_INVALID_PROPERTY;
|
||||
return;
|
||||
}
|
||||
if (prop->propKind != CS_PROP_ENUM) {
|
||||
*status = CS_WRONG_PROPERTY_TYPE;
|
||||
return;
|
||||
}
|
||||
prop->enumChoices = choices;
|
||||
m_notifier.NotifySourceProperty(*this, CS_SOURCE_PROPERTY_CHOICES_UPDATED,
|
||||
prop->name, property, CS_PROP_ENUM,
|
||||
prop->value, wpi::Twine{});
|
||||
}
|
||||
56
cscore/src/main/native/cpp/ConfigurableSourceImpl.h
Normal file
56
cscore/src/main/native/cpp/ConfigurableSourceImpl.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef CSCORE_CONFIGURABLESOURCEIMPL_H_
|
||||
#define CSCORE_CONFIGURABLESOURCEIMPL_H_
|
||||
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <wpi/ArrayRef.h>
|
||||
#include <wpi/Twine.h>
|
||||
|
||||
#include "SourceImpl.h"
|
||||
|
||||
namespace cs {
|
||||
|
||||
class ConfigurableSourceImpl : public SourceImpl {
|
||||
protected:
|
||||
ConfigurableSourceImpl(const wpi::Twine& name, wpi::Logger& logger,
|
||||
Notifier& notifier, Telemetry& telemetry,
|
||||
const VideoMode& mode);
|
||||
|
||||
public:
|
||||
~ConfigurableSourceImpl() override;
|
||||
|
||||
void Start() override;
|
||||
|
||||
bool SetVideoMode(const VideoMode& mode, CS_Status* status) override;
|
||||
|
||||
void NumSinksChanged() override;
|
||||
void NumSinksEnabledChanged() override;
|
||||
|
||||
// OpenCV-specific functions
|
||||
void NotifyError(const wpi::Twine& msg);
|
||||
int CreateProperty(const wpi::Twine& name, CS_PropertyKind kind, int minimum,
|
||||
int maximum, int step, int defaultValue, int value);
|
||||
int CreateProperty(const wpi::Twine& name, CS_PropertyKind kind, int minimum,
|
||||
int maximum, int step, int defaultValue, int value,
|
||||
std::function<void(CS_Property property)> onChange);
|
||||
void SetEnumPropertyChoices(int property, wpi::ArrayRef<std::string> choices,
|
||||
CS_Status* status);
|
||||
|
||||
private:
|
||||
std::atomic_bool m_connected{true};
|
||||
};
|
||||
|
||||
} // namespace cs
|
||||
|
||||
#endif // CSCORE_CONFIGURABLESOURCEIMPL_H_
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
@@ -138,10 +138,12 @@ CS_Sink CreateCvSinkCallback(const wpi::Twine& name,
|
||||
inst.telemetry, processFrame));
|
||||
}
|
||||
|
||||
static constexpr unsigned SinkMask = CS_SINK_CV | CS_SINK_RAW;
|
||||
|
||||
void SetSinkDescription(CS_Sink sink, const wpi::Twine& description,
|
||||
CS_Status* status) {
|
||||
auto data = Instance::GetInstance().GetSink(sink);
|
||||
if (!data || data->kind != CS_SINK_CV) {
|
||||
if (!data || (data->kind & SinkMask) == 0) {
|
||||
*status = CS_INVALID_HANDLE;
|
||||
return;
|
||||
}
|
||||
@@ -169,7 +171,7 @@ uint64_t GrabSinkFrameTimeout(CS_Sink sink, cv::Mat& image, double timeout,
|
||||
|
||||
std::string GetSinkError(CS_Sink sink, CS_Status* status) {
|
||||
auto data = Instance::GetInstance().GetSink(sink);
|
||||
if (!data || data->kind != CS_SINK_CV) {
|
||||
if (!data || (data->kind & SinkMask) == 0) {
|
||||
*status = CS_INVALID_HANDLE;
|
||||
return std::string{};
|
||||
}
|
||||
@@ -179,7 +181,7 @@ std::string GetSinkError(CS_Sink sink, CS_Status* status) {
|
||||
wpi::StringRef GetSinkError(CS_Sink sink, wpi::SmallVectorImpl<char>& buf,
|
||||
CS_Status* status) {
|
||||
auto data = Instance::GetInstance().GetSink(sink);
|
||||
if (!data || data->kind != CS_SINK_CV) {
|
||||
if (!data || (data->kind & SinkMask) == 0) {
|
||||
*status = CS_INVALID_HANDLE;
|
||||
return wpi::StringRef{};
|
||||
}
|
||||
@@ -188,7 +190,7 @@ wpi::StringRef GetSinkError(CS_Sink sink, wpi::SmallVectorImpl<char>& buf,
|
||||
|
||||
void SetSinkEnabled(CS_Sink sink, bool enabled, CS_Status* status) {
|
||||
auto data = Instance::GetInstance().GetSink(sink);
|
||||
if (!data || data->kind != CS_SINK_CV) {
|
||||
if (!data || (data->kind & SinkMask) == 0) {
|
||||
*status = CS_INVALID_HANDLE;
|
||||
return;
|
||||
}
|
||||
@@ -215,6 +217,7 @@ void CS_SetSinkDescription(CS_Sink sink, const char* description,
|
||||
return cs::SetSinkDescription(sink, description, status);
|
||||
}
|
||||
|
||||
#if CV_VERSION_MAJOR < 4
|
||||
uint64_t CS_GrabSinkFrame(CS_Sink sink, struct CvMat* image,
|
||||
CS_Status* status) {
|
||||
auto mat = cv::cvarrToMat(image);
|
||||
@@ -226,6 +229,7 @@ uint64_t CS_GrabSinkFrameTimeout(CS_Sink sink, struct CvMat* image,
|
||||
auto mat = cv::cvarrToMat(image);
|
||||
return cs::GrabSinkFrameTimeout(sink, mat, timeout, status);
|
||||
}
|
||||
#endif // CV_VERSION_MAJOR < 4
|
||||
|
||||
uint64_t CS_GrabSinkFrameCpp(CS_Sink sink, cv::Mat* image, CS_Status* status) {
|
||||
return cs::GrabSinkFrame(sink, *image, status);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
@@ -25,37 +25,10 @@ using namespace cs;
|
||||
CvSourceImpl::CvSourceImpl(const wpi::Twine& name, wpi::Logger& logger,
|
||||
Notifier& notifier, Telemetry& telemetry,
|
||||
const VideoMode& mode)
|
||||
: SourceImpl{name, logger, notifier, telemetry} {
|
||||
m_mode = mode;
|
||||
m_videoModes.push_back(m_mode);
|
||||
}
|
||||
: ConfigurableSourceImpl{name, logger, notifier, telemetry, mode} {}
|
||||
|
||||
CvSourceImpl::~CvSourceImpl() {}
|
||||
|
||||
void CvSourceImpl::Start() {
|
||||
m_notifier.NotifySource(*this, CS_SOURCE_CONNECTED);
|
||||
m_notifier.NotifySource(*this, CS_SOURCE_VIDEOMODES_UPDATED);
|
||||
m_notifier.NotifySourceVideoMode(*this, m_mode);
|
||||
}
|
||||
|
||||
bool CvSourceImpl::SetVideoMode(const VideoMode& mode, CS_Status* status) {
|
||||
{
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
m_mode = mode;
|
||||
m_videoModes[0] = mode;
|
||||
}
|
||||
m_notifier.NotifySourceVideoMode(*this, mode);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CvSourceImpl::NumSinksChanged() {
|
||||
// ignore
|
||||
}
|
||||
|
||||
void CvSourceImpl::NumSinksEnabledChanged() {
|
||||
// ignore
|
||||
}
|
||||
|
||||
void CvSourceImpl::PutFrame(cv::Mat& image) {
|
||||
// We only support 8-bit images; convert if necessary.
|
||||
cv::Mat finalImage;
|
||||
@@ -89,61 +62,6 @@ void CvSourceImpl::PutFrame(cv::Mat& image) {
|
||||
SourceImpl::PutFrame(std::move(dest), wpi::Now());
|
||||
}
|
||||
|
||||
void CvSourceImpl::NotifyError(const wpi::Twine& msg) {
|
||||
PutError(msg, wpi::Now());
|
||||
}
|
||||
|
||||
int CvSourceImpl::CreateProperty(const wpi::Twine& name, CS_PropertyKind kind,
|
||||
int minimum, int maximum, int step,
|
||||
int defaultValue, int value) {
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
int ndx = CreateOrUpdateProperty(name,
|
||||
[=] {
|
||||
return wpi::make_unique<PropertyImpl>(
|
||||
name, kind, minimum, maximum, step,
|
||||
defaultValue, value);
|
||||
},
|
||||
[&](PropertyImpl& prop) {
|
||||
// update all but value
|
||||
prop.propKind = kind;
|
||||
prop.minimum = minimum;
|
||||
prop.maximum = maximum;
|
||||
prop.step = step;
|
||||
prop.defaultValue = defaultValue;
|
||||
value = prop.value;
|
||||
});
|
||||
m_notifier.NotifySourceProperty(*this, CS_SOURCE_PROPERTY_CREATED, name, ndx,
|
||||
kind, value, wpi::Twine{});
|
||||
return ndx;
|
||||
}
|
||||
|
||||
int CvSourceImpl::CreateProperty(
|
||||
const wpi::Twine& name, CS_PropertyKind kind, int minimum, int maximum,
|
||||
int step, int defaultValue, int value,
|
||||
std::function<void(CS_Property property)> onChange) {
|
||||
// TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CvSourceImpl::SetEnumPropertyChoices(int property,
|
||||
wpi::ArrayRef<std::string> choices,
|
||||
CS_Status* status) {
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
auto prop = GetProperty(property);
|
||||
if (!prop) {
|
||||
*status = CS_INVALID_PROPERTY;
|
||||
return;
|
||||
}
|
||||
if (prop->propKind != CS_PROP_ENUM) {
|
||||
*status = CS_WRONG_PROPERTY_TYPE;
|
||||
return;
|
||||
}
|
||||
prop->enumChoices = choices;
|
||||
m_notifier.NotifySourceProperty(*this, CS_SOURCE_PROPERTY_CHOICES_UPDATED,
|
||||
prop->name, property, CS_PROP_ENUM,
|
||||
prop->value, wpi::Twine{});
|
||||
}
|
||||
|
||||
namespace cs {
|
||||
|
||||
CS_Source CreateCvSource(const wpi::Twine& name, const VideoMode& mode,
|
||||
@@ -163,10 +81,12 @@ void PutSourceFrame(CS_Source source, cv::Mat& image, CS_Status* status) {
|
||||
static_cast<CvSourceImpl&>(*data->source).PutFrame(image);
|
||||
}
|
||||
|
||||
static constexpr unsigned SourceMask = CS_SINK_CV | CS_SINK_RAW;
|
||||
|
||||
void NotifySourceError(CS_Source source, const wpi::Twine& msg,
|
||||
CS_Status* status) {
|
||||
auto data = Instance::GetInstance().GetSource(source);
|
||||
if (!data || data->kind != CS_SOURCE_CV) {
|
||||
if (!data || (data->kind & SourceMask) == 0) {
|
||||
*status = CS_INVALID_HANDLE;
|
||||
return;
|
||||
}
|
||||
@@ -175,7 +95,7 @@ void NotifySourceError(CS_Source source, const wpi::Twine& msg,
|
||||
|
||||
void SetSourceConnected(CS_Source source, bool connected, CS_Status* status) {
|
||||
auto data = Instance::GetInstance().GetSource(source);
|
||||
if (!data || data->kind != CS_SOURCE_CV) {
|
||||
if (!data || (data->kind & SourceMask) == 0) {
|
||||
*status = CS_INVALID_HANDLE;
|
||||
return;
|
||||
}
|
||||
@@ -185,7 +105,7 @@ void SetSourceConnected(CS_Source source, bool connected, CS_Status* status) {
|
||||
void SetSourceDescription(CS_Source source, const wpi::Twine& description,
|
||||
CS_Status* status) {
|
||||
auto data = Instance::GetInstance().GetSource(source);
|
||||
if (!data || data->kind != CS_SOURCE_CV) {
|
||||
if (!data || (data->kind & SourceMask) == 0) {
|
||||
*status = CS_INVALID_HANDLE;
|
||||
return;
|
||||
}
|
||||
@@ -197,7 +117,7 @@ CS_Property CreateSourceProperty(CS_Source source, const wpi::Twine& name,
|
||||
int step, int defaultValue, int value,
|
||||
CS_Status* status) {
|
||||
auto data = Instance::GetInstance().GetSource(source);
|
||||
if (!data || data->kind != CS_SOURCE_CV) {
|
||||
if (!data || (data->kind & SourceMask) == 0) {
|
||||
*status = CS_INVALID_HANDLE;
|
||||
return -1;
|
||||
}
|
||||
@@ -212,7 +132,7 @@ CS_Property CreateSourcePropertyCallback(
|
||||
int maximum, int step, int defaultValue, int value,
|
||||
std::function<void(CS_Property property)> onChange, CS_Status* status) {
|
||||
auto data = Instance::GetInstance().GetSource(source);
|
||||
if (!data || data->kind != CS_SOURCE_CV) {
|
||||
if (!data || (data->kind & SourceMask) == 0) {
|
||||
*status = CS_INVALID_HANDLE;
|
||||
return -1;
|
||||
}
|
||||
@@ -226,7 +146,7 @@ void SetSourceEnumPropertyChoices(CS_Source source, CS_Property property,
|
||||
wpi::ArrayRef<std::string> choices,
|
||||
CS_Status* status) {
|
||||
auto data = Instance::GetInstance().GetSource(source);
|
||||
if (!data || data->kind != CS_SOURCE_CV) {
|
||||
if (!data || (data->kind & SourceMask) == 0) {
|
||||
*status = CS_INVALID_HANDLE;
|
||||
return;
|
||||
}
|
||||
@@ -258,11 +178,13 @@ CS_Source CS_CreateCvSource(const char* name, const CS_VideoMode* mode,
|
||||
status);
|
||||
}
|
||||
|
||||
#if CV_VERSION_MAJOR < 4
|
||||
void CS_PutSourceFrame(CS_Source source, struct CvMat* image,
|
||||
CS_Status* status) {
|
||||
auto mat = cv::cvarrToMat(image);
|
||||
return cs::PutSourceFrame(source, mat, status);
|
||||
}
|
||||
#endif // CV_VERSION_MAJOR < 4
|
||||
|
||||
void CS_PutSourceFrameCpp(CS_Source source, cv::Mat* image, CS_Status* status) {
|
||||
return cs::PutSourceFrame(source, *image, status);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
@@ -18,33 +18,19 @@
|
||||
#include <wpi/ArrayRef.h>
|
||||
#include <wpi/Twine.h>
|
||||
|
||||
#include "ConfigurableSourceImpl.h"
|
||||
#include "SourceImpl.h"
|
||||
|
||||
namespace cs {
|
||||
|
||||
class CvSourceImpl : public SourceImpl {
|
||||
class CvSourceImpl : public ConfigurableSourceImpl {
|
||||
public:
|
||||
CvSourceImpl(const wpi::Twine& name, wpi::Logger& logger, Notifier& notifier,
|
||||
Telemetry& telemetry, const VideoMode& mode);
|
||||
~CvSourceImpl() override;
|
||||
|
||||
void Start() override;
|
||||
|
||||
bool SetVideoMode(const VideoMode& mode, CS_Status* status) override;
|
||||
|
||||
void NumSinksChanged() override;
|
||||
void NumSinksEnabledChanged() override;
|
||||
|
||||
// OpenCV-specific functions
|
||||
void PutFrame(cv::Mat& image);
|
||||
void NotifyError(const wpi::Twine& msg);
|
||||
int CreateProperty(const wpi::Twine& name, CS_PropertyKind kind, int minimum,
|
||||
int maximum, int step, int defaultValue, int value);
|
||||
int CreateProperty(const wpi::Twine& name, CS_PropertyKind kind, int minimum,
|
||||
int maximum, int step, int defaultValue, int value,
|
||||
std::function<void(CS_Property property)> onChange);
|
||||
void SetEnumPropertyChoices(int property, wpi::ArrayRef<std::string> choices,
|
||||
CS_Status* status);
|
||||
|
||||
private:
|
||||
std::atomic_bool m_connected{true};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
@@ -36,7 +36,7 @@ Frame::Frame(SourceImpl& source, std::unique_ptr<Image> image, Time time)
|
||||
|
||||
Image* Frame::GetNearestImage(int width, int height) const {
|
||||
if (!m_impl) return nullptr;
|
||||
std::lock_guard<wpi::recursive_mutex> lock(m_impl->mutex);
|
||||
std::scoped_lock lock(m_impl->mutex);
|
||||
Image* found = nullptr;
|
||||
|
||||
// Ideally we want the smallest image at least width/height in size
|
||||
@@ -60,7 +60,7 @@ Image* Frame::GetNearestImage(int width, int height,
|
||||
VideoMode::PixelFormat pixelFormat,
|
||||
int jpegQuality) const {
|
||||
if (!m_impl) return nullptr;
|
||||
std::lock_guard<wpi::recursive_mutex> lock(m_impl->mutex);
|
||||
std::scoped_lock lock(m_impl->mutex);
|
||||
Image* found = nullptr;
|
||||
|
||||
// We want the smallest image at least width/height (or the next largest),
|
||||
@@ -253,7 +253,7 @@ Image* Frame::ConvertMJPEGToBGR(Image* image) {
|
||||
// Save the result
|
||||
Image* rv = newImage.release();
|
||||
if (m_impl) {
|
||||
std::lock_guard<wpi::recursive_mutex> lock(m_impl->mutex);
|
||||
std::scoped_lock lock(m_impl->mutex);
|
||||
m_impl->images.push_back(rv);
|
||||
}
|
||||
return rv;
|
||||
@@ -274,7 +274,7 @@ Image* Frame::ConvertMJPEGToGray(Image* image) {
|
||||
// Save the result
|
||||
Image* rv = newImage.release();
|
||||
if (m_impl) {
|
||||
std::lock_guard<wpi::recursive_mutex> lock(m_impl->mutex);
|
||||
std::scoped_lock lock(m_impl->mutex);
|
||||
m_impl->images.push_back(rv);
|
||||
}
|
||||
return rv;
|
||||
@@ -294,7 +294,7 @@ Image* Frame::ConvertYUYVToBGR(Image* image) {
|
||||
// Save the result
|
||||
Image* rv = newImage.release();
|
||||
if (m_impl) {
|
||||
std::lock_guard<wpi::recursive_mutex> lock(m_impl->mutex);
|
||||
std::scoped_lock lock(m_impl->mutex);
|
||||
m_impl->images.push_back(rv);
|
||||
}
|
||||
return rv;
|
||||
@@ -314,7 +314,7 @@ Image* Frame::ConvertBGRToRGB565(Image* image) {
|
||||
// Save the result
|
||||
Image* rv = newImage.release();
|
||||
if (m_impl) {
|
||||
std::lock_guard<wpi::recursive_mutex> lock(m_impl->mutex);
|
||||
std::scoped_lock lock(m_impl->mutex);
|
||||
m_impl->images.push_back(rv);
|
||||
}
|
||||
return rv;
|
||||
@@ -334,7 +334,7 @@ Image* Frame::ConvertRGB565ToBGR(Image* image) {
|
||||
// Save the result
|
||||
Image* rv = newImage.release();
|
||||
if (m_impl) {
|
||||
std::lock_guard<wpi::recursive_mutex> lock(m_impl->mutex);
|
||||
std::scoped_lock lock(m_impl->mutex);
|
||||
m_impl->images.push_back(rv);
|
||||
}
|
||||
return rv;
|
||||
@@ -354,14 +354,14 @@ Image* Frame::ConvertBGRToGray(Image* image) {
|
||||
// Save the result
|
||||
Image* rv = newImage.release();
|
||||
if (m_impl) {
|
||||
std::lock_guard<wpi::recursive_mutex> lock(m_impl->mutex);
|
||||
std::scoped_lock lock(m_impl->mutex);
|
||||
m_impl->images.push_back(rv);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
Image* Frame::ConvertGrayToBGR(Image* image) {
|
||||
if (!image || image->pixelFormat != VideoMode::kBGR) return nullptr;
|
||||
if (!image || image->pixelFormat != VideoMode::kGray) return nullptr;
|
||||
|
||||
// Allocate a BGR image
|
||||
auto newImage =
|
||||
@@ -374,7 +374,7 @@ Image* Frame::ConvertGrayToBGR(Image* image) {
|
||||
// Save the result
|
||||
Image* rv = newImage.release();
|
||||
if (m_impl) {
|
||||
std::lock_guard<wpi::recursive_mutex> lock(m_impl->mutex);
|
||||
std::scoped_lock lock(m_impl->mutex);
|
||||
m_impl->images.push_back(rv);
|
||||
}
|
||||
return rv;
|
||||
@@ -383,7 +383,7 @@ Image* Frame::ConvertGrayToBGR(Image* image) {
|
||||
Image* Frame::ConvertBGRToMJPEG(Image* image, int quality) {
|
||||
if (!image || image->pixelFormat != VideoMode::kBGR) return nullptr;
|
||||
if (!m_impl) return nullptr;
|
||||
std::lock_guard<wpi::recursive_mutex> lock(m_impl->mutex);
|
||||
std::scoped_lock lock(m_impl->mutex);
|
||||
|
||||
// Allocate a JPEG image. We don't actually know what the resulting size
|
||||
// will be; while the destination will automatically grow, doing so will
|
||||
@@ -397,7 +397,7 @@ Image* Frame::ConvertBGRToMJPEG(Image* image, int quality) {
|
||||
|
||||
// Compress
|
||||
if (m_impl->compressionParams.empty()) {
|
||||
m_impl->compressionParams.push_back(CV_IMWRITE_JPEG_QUALITY);
|
||||
m_impl->compressionParams.push_back(cv::IMWRITE_JPEG_QUALITY);
|
||||
m_impl->compressionParams.push_back(quality);
|
||||
} else {
|
||||
m_impl->compressionParams[1] = quality;
|
||||
@@ -414,7 +414,7 @@ Image* Frame::ConvertBGRToMJPEG(Image* image, int quality) {
|
||||
Image* Frame::ConvertGrayToMJPEG(Image* image, int quality) {
|
||||
if (!image || image->pixelFormat != VideoMode::kGray) return nullptr;
|
||||
if (!m_impl) return nullptr;
|
||||
std::lock_guard<wpi::recursive_mutex> lock(m_impl->mutex);
|
||||
std::scoped_lock lock(m_impl->mutex);
|
||||
|
||||
// Allocate a JPEG image. We don't actually know what the resulting size
|
||||
// will be; while the destination will automatically grow, doing so will
|
||||
@@ -428,7 +428,7 @@ Image* Frame::ConvertGrayToMJPEG(Image* image, int quality) {
|
||||
|
||||
// Compress
|
||||
if (m_impl->compressionParams.empty()) {
|
||||
m_impl->compressionParams.push_back(CV_IMWRITE_JPEG_QUALITY);
|
||||
m_impl->compressionParams.push_back(cv::IMWRITE_JPEG_QUALITY);
|
||||
m_impl->compressionParams.push_back(quality);
|
||||
} else {
|
||||
m_impl->compressionParams[1] = quality;
|
||||
@@ -446,7 +446,7 @@ Image* Frame::GetImageImpl(int width, int height,
|
||||
VideoMode::PixelFormat pixelFormat,
|
||||
int requiredJpegQuality, int defaultJpegQuality) {
|
||||
if (!m_impl) return nullptr;
|
||||
std::lock_guard<wpi::recursive_mutex> lock(m_impl->mutex);
|
||||
std::scoped_lock lock(m_impl->mutex);
|
||||
Image* cur = GetNearestImage(width, height, pixelFormat, requiredJpegQuality);
|
||||
if (!cur || cur->Is(width, height, pixelFormat, requiredJpegQuality))
|
||||
return cur;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
@@ -80,42 +80,42 @@ class Frame {
|
||||
|
||||
int GetOriginalWidth() const {
|
||||
if (!m_impl) return 0;
|
||||
std::lock_guard<wpi::recursive_mutex> lock(m_impl->mutex);
|
||||
std::scoped_lock lock(m_impl->mutex);
|
||||
if (m_impl->images.empty()) return 0;
|
||||
return m_impl->images[0]->width;
|
||||
}
|
||||
|
||||
int GetOriginalHeight() const {
|
||||
if (!m_impl) return 0;
|
||||
std::lock_guard<wpi::recursive_mutex> lock(m_impl->mutex);
|
||||
std::scoped_lock lock(m_impl->mutex);
|
||||
if (m_impl->images.empty()) return 0;
|
||||
return m_impl->images[0]->height;
|
||||
}
|
||||
|
||||
int GetOriginalPixelFormat() const {
|
||||
if (!m_impl) return 0;
|
||||
std::lock_guard<wpi::recursive_mutex> lock(m_impl->mutex);
|
||||
std::scoped_lock lock(m_impl->mutex);
|
||||
if (m_impl->images.empty()) return 0;
|
||||
return m_impl->images[0]->pixelFormat;
|
||||
}
|
||||
|
||||
int GetOriginalJpegQuality() const {
|
||||
if (!m_impl) return 0;
|
||||
std::lock_guard<wpi::recursive_mutex> lock(m_impl->mutex);
|
||||
std::scoped_lock lock(m_impl->mutex);
|
||||
if (m_impl->images.empty()) return 0;
|
||||
return m_impl->images[0]->jpegQuality;
|
||||
}
|
||||
|
||||
Image* GetExistingImage(size_t i = 0) const {
|
||||
if (!m_impl) return nullptr;
|
||||
std::lock_guard<wpi::recursive_mutex> lock(m_impl->mutex);
|
||||
std::scoped_lock lock(m_impl->mutex);
|
||||
if (i >= m_impl->images.size()) return nullptr;
|
||||
return m_impl->images[i];
|
||||
}
|
||||
|
||||
Image* GetExistingImage(int width, int height) const {
|
||||
if (!m_impl) return nullptr;
|
||||
std::lock_guard<wpi::recursive_mutex> lock(m_impl->mutex);
|
||||
std::scoped_lock lock(m_impl->mutex);
|
||||
for (auto i : m_impl->images) {
|
||||
if (i->Is(width, height)) return i;
|
||||
}
|
||||
@@ -125,7 +125,7 @@ class Frame {
|
||||
Image* GetExistingImage(int width, int height,
|
||||
VideoMode::PixelFormat pixelFormat) const {
|
||||
if (!m_impl) return nullptr;
|
||||
std::lock_guard<wpi::recursive_mutex> lock(m_impl->mutex);
|
||||
std::scoped_lock lock(m_impl->mutex);
|
||||
for (auto i : m_impl->images) {
|
||||
if (i->Is(width, height, pixelFormat)) return i;
|
||||
}
|
||||
@@ -136,7 +136,7 @@ class Frame {
|
||||
VideoMode::PixelFormat pixelFormat,
|
||||
int jpegQuality) const {
|
||||
if (!m_impl) return nullptr;
|
||||
std::lock_guard<wpi::recursive_mutex> lock(m_impl->mutex);
|
||||
std::scoped_lock lock(m_impl->mutex);
|
||||
for (auto i : m_impl->images) {
|
||||
if (i->Is(width, height, pixelFormat, jpegQuality)) return i;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
@@ -7,9 +7,8 @@
|
||||
|
||||
#include "HttpCameraImpl.h"
|
||||
|
||||
#include <wpi/STLExtras.h>
|
||||
#include <wpi/MemAlloc.h>
|
||||
#include <wpi/TCPConnector.h>
|
||||
#include <wpi/memory.h>
|
||||
#include <wpi/timestamp.h>
|
||||
|
||||
#include "Handle.h"
|
||||
@@ -38,7 +37,7 @@ HttpCameraImpl::~HttpCameraImpl() {
|
||||
|
||||
// Close file if it's open
|
||||
{
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
if (m_streamConn) m_streamConn->stream->close();
|
||||
if (m_settingsConn) m_settingsConn->stream->close();
|
||||
}
|
||||
@@ -65,7 +64,7 @@ void HttpCameraImpl::Start() {
|
||||
|
||||
void HttpCameraImpl::MonitorThreadMain() {
|
||||
while (m_active) {
|
||||
std::unique_lock<wpi::mutex> lock(m_mutex);
|
||||
std::unique_lock lock(m_mutex);
|
||||
// sleep for 1 second between checks
|
||||
m_monitorCond.wait_for(lock, std::chrono::seconds(1),
|
||||
[=] { return !m_active; });
|
||||
@@ -96,7 +95,7 @@ void HttpCameraImpl::StreamThreadMain() {
|
||||
|
||||
// disconnect if not enabled
|
||||
if (!IsEnabled()) {
|
||||
std::unique_lock<wpi::mutex> lock(m_mutex);
|
||||
std::unique_lock lock(m_mutex);
|
||||
if (m_streamConn) m_streamConn->stream->close();
|
||||
// Wait for enable
|
||||
m_sinkEnabledCond.wait(lock, [=] { return !m_active || IsEnabled(); });
|
||||
@@ -118,7 +117,7 @@ void HttpCameraImpl::StreamThreadMain() {
|
||||
// stream
|
||||
DeviceStream(conn->is, boundary);
|
||||
{
|
||||
std::unique_lock<wpi::mutex> lock(m_mutex);
|
||||
std::unique_lock lock(m_mutex);
|
||||
m_streamConn = nullptr;
|
||||
}
|
||||
}
|
||||
@@ -132,7 +131,7 @@ wpi::HttpConnection* HttpCameraImpl::DeviceStreamConnect(
|
||||
// Build the request
|
||||
wpi::HttpRequest req;
|
||||
{
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
if (m_locations.empty()) {
|
||||
SERROR("locations array is empty!?");
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
@@ -149,12 +148,12 @@ wpi::HttpConnection* HttpCameraImpl::DeviceStreamConnect(
|
||||
|
||||
if (!m_active || !stream) return nullptr;
|
||||
|
||||
auto connPtr = wpi::make_unique<wpi::HttpConnection>(std::move(stream), 1);
|
||||
auto connPtr = std::make_unique<wpi::HttpConnection>(std::move(stream), 1);
|
||||
wpi::HttpConnection* conn = connPtr.get();
|
||||
|
||||
// update m_streamConn
|
||||
{
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
m_frameCount = 1; // avoid a race with monitor thread
|
||||
m_streamConn = std::move(connPtr);
|
||||
}
|
||||
@@ -162,7 +161,7 @@ wpi::HttpConnection* HttpCameraImpl::DeviceStreamConnect(
|
||||
std::string warn;
|
||||
if (!conn->Handshake(req, &warn)) {
|
||||
SWARNING(GetName() << ": " << warn);
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
m_streamConn = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
@@ -174,7 +173,7 @@ wpi::HttpConnection* HttpCameraImpl::DeviceStreamConnect(
|
||||
if (mediaType != "multipart/x-mixed-replace") {
|
||||
SWARNING("\"" << req.host << "\": unrecognized Content-Type \"" << mediaType
|
||||
<< "\"");
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
m_streamConn = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
@@ -189,6 +188,9 @@ wpi::HttpConnection* HttpCameraImpl::DeviceStreamConnect(
|
||||
std::tie(key, value) = keyvalue.split('=');
|
||||
if (key.trim() == "boundary") {
|
||||
value = value.trim().trim('"'); // value may be quoted
|
||||
if (value.startswith("--")) {
|
||||
value = value.substr(2);
|
||||
}
|
||||
boundary.append(value.begin(), value.end());
|
||||
}
|
||||
}
|
||||
@@ -196,7 +198,7 @@ wpi::HttpConnection* HttpCameraImpl::DeviceStreamConnect(
|
||||
if (boundary.empty()) {
|
||||
SWARNING("\"" << req.host
|
||||
<< "\": empty multi-part boundary or no Content-Type");
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
m_streamConn = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
@@ -219,11 +221,16 @@ void HttpCameraImpl::DeviceStream(wpi::raw_istream& is,
|
||||
if (!FindMultipartBoundary(is, boundary, nullptr)) break;
|
||||
|
||||
// Read the next two characters after the boundary (normally \r\n)
|
||||
// Handle just \n for LabVIEW however
|
||||
char eol[2];
|
||||
is.read(eol, 2);
|
||||
is.read(eol, 1);
|
||||
if (!m_active || is.has_error()) break;
|
||||
// End-of-stream is indicated with trailing --
|
||||
if (eol[0] == '-' && eol[1] == '-') break;
|
||||
if (eol[0] != '\n') {
|
||||
is.read(eol + 1, 1);
|
||||
if (!m_active || is.has_error()) break;
|
||||
// End-of-stream is indicated with trailing --
|
||||
if (eol[0] == '-' && eol[1] == '-') break;
|
||||
}
|
||||
|
||||
if (!DeviceStreamFrame(is, imageBuf))
|
||||
++numErrors;
|
||||
@@ -291,7 +298,7 @@ void HttpCameraImpl::SettingsThreadMain() {
|
||||
for (;;) {
|
||||
wpi::HttpRequest req;
|
||||
{
|
||||
std::unique_lock<wpi::mutex> lock(m_mutex);
|
||||
std::unique_lock lock(m_mutex);
|
||||
m_settingsCond.wait(lock, [=] {
|
||||
return !m_active || (m_prefLocation != -1 && !m_settings.empty());
|
||||
});
|
||||
@@ -314,12 +321,12 @@ void HttpCameraImpl::DeviceSendSettings(wpi::HttpRequest& req) {
|
||||
|
||||
if (!m_active || !stream) return;
|
||||
|
||||
auto connPtr = wpi::make_unique<wpi::HttpConnection>(std::move(stream), 1);
|
||||
auto connPtr = std::make_unique<wpi::HttpConnection>(std::move(stream), 1);
|
||||
wpi::HttpConnection* conn = connPtr.get();
|
||||
|
||||
// update m_settingsConn
|
||||
{
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
m_settingsConn = std::move(connPtr);
|
||||
}
|
||||
|
||||
@@ -331,7 +338,7 @@ void HttpCameraImpl::DeviceSendSettings(wpi::HttpRequest& req) {
|
||||
}
|
||||
|
||||
CS_HttpCameraKind HttpCameraImpl::GetKind() const {
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
return m_kind;
|
||||
}
|
||||
|
||||
@@ -349,7 +356,7 @@ bool HttpCameraImpl::SetUrls(wpi::ArrayRef<std::string> urls,
|
||||
}
|
||||
}
|
||||
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
m_locations.swap(locations);
|
||||
m_nextLocation = 0;
|
||||
m_streamSettingsUpdated = true;
|
||||
@@ -357,7 +364,7 @@ bool HttpCameraImpl::SetUrls(wpi::ArrayRef<std::string> urls,
|
||||
}
|
||||
|
||||
std::vector<std::string> HttpCameraImpl::GetUrls() const {
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
std::vector<std::string> urls;
|
||||
for (const auto& loc : m_locations) urls.push_back(loc.url);
|
||||
return urls;
|
||||
@@ -368,8 +375,8 @@ void HttpCameraImpl::CreateProperty(const wpi::Twine& name,
|
||||
bool viaSettings, CS_PropertyKind kind,
|
||||
int minimum, int maximum, int step,
|
||||
int defaultValue, int value) const {
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
m_propertyData.emplace_back(wpi::make_unique<PropertyData>(
|
||||
std::scoped_lock lock(m_mutex);
|
||||
m_propertyData.emplace_back(std::make_unique<PropertyData>(
|
||||
name, httpParam, viaSettings, kind, minimum, maximum, step, defaultValue,
|
||||
value));
|
||||
|
||||
@@ -382,8 +389,8 @@ template <typename T>
|
||||
void HttpCameraImpl::CreateEnumProperty(
|
||||
const wpi::Twine& name, const wpi::Twine& httpParam, bool viaSettings,
|
||||
int defaultValue, int value, std::initializer_list<T> choices) const {
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
m_propertyData.emplace_back(wpi::make_unique<PropertyData>(
|
||||
std::scoped_lock lock(m_mutex);
|
||||
m_propertyData.emplace_back(std::make_unique<PropertyData>(
|
||||
name, httpParam, viaSettings, CS_PROP_ENUM, 0, choices.size() - 1, 1,
|
||||
defaultValue, value));
|
||||
|
||||
@@ -401,11 +408,15 @@ void HttpCameraImpl::CreateEnumProperty(
|
||||
|
||||
std::unique_ptr<PropertyImpl> HttpCameraImpl::CreateEmptyProperty(
|
||||
const wpi::Twine& name) const {
|
||||
return wpi::make_unique<PropertyData>(name);
|
||||
return std::make_unique<PropertyData>(name);
|
||||
}
|
||||
|
||||
bool HttpCameraImpl::CacheProperties(CS_Status* status) const {
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
#ifdef _MSC_VER // work around VS2019 16.4.0 bug
|
||||
std::scoped_lock<wpi::mutex> lock(m_mutex);
|
||||
#else
|
||||
std::scoped_lock lock(m_mutex);
|
||||
#endif
|
||||
|
||||
// Pretty typical set of video modes
|
||||
m_videoModes.clear();
|
||||
@@ -461,7 +472,7 @@ void HttpCameraImpl::SetExposureManual(int value, CS_Status* status) {
|
||||
|
||||
bool HttpCameraImpl::SetVideoMode(const VideoMode& mode, CS_Status* status) {
|
||||
if (mode.pixelFormat != VideoMode::kMJPEG) return false;
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
m_mode = mode;
|
||||
m_streamSettingsUpdated = true;
|
||||
return true;
|
||||
@@ -490,7 +501,7 @@ bool AxisCameraImpl::CacheProperties(CS_Status* status) const {
|
||||
true, CS_PROP_INTEGER, 0, 100, 1, 50, 50);
|
||||
|
||||
// TODO: get video modes from device
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
m_videoModes.clear();
|
||||
m_videoModes.emplace_back(VideoMode::kMJPEG, 640, 480, 30);
|
||||
m_videoModes.emplace_back(VideoMode::kMJPEG, 480, 360, 30);
|
||||
@@ -603,7 +614,7 @@ void CS_SetHttpCameraUrls(CS_Source source, const char** urls, int count,
|
||||
char** CS_GetHttpCameraUrls(CS_Source source, int* count, CS_Status* status) {
|
||||
auto urls = cs::GetHttpCameraUrls(source, status);
|
||||
char** out =
|
||||
static_cast<char**>(wpi::CheckedMalloc(urls.size() * sizeof(char*)));
|
||||
static_cast<char**>(wpi::safe_malloc(urls.size() * sizeof(char*)));
|
||||
*count = urls.size();
|
||||
for (size_t i = 0; i < urls.size(); ++i) out[i] = cs::ConvertToC(urls[i]);
|
||||
return out;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
@@ -17,7 +17,7 @@
|
||||
#define WARNING(x) WPI_WARNING(m_logger, x)
|
||||
#define INFO(x) WPI_INFO(m_logger, x)
|
||||
|
||||
#define DEBUG(x) WPI_DEBUG(m_logger, x)
|
||||
#define DEBUG0(x) WPI_DEBUG(m_logger, x)
|
||||
#define DEBUG1(x) WPI_DEBUG1(m_logger, x)
|
||||
#define DEBUG2(x) WPI_DEBUG2(m_logger, x)
|
||||
#define DEBUG3(x) WPI_DEBUG3(m_logger, x)
|
||||
@@ -27,7 +27,7 @@
|
||||
#define SWARNING(x) WARNING(GetName() << ": " << x)
|
||||
#define SINFO(x) INFO(GetName() << ": " << x)
|
||||
|
||||
#define SDEBUG(x) DEBUG(GetName() << ": " << x)
|
||||
#define SDEBUG(x) DEBUG0(GetName() << ": " << x)
|
||||
#define SDEBUG1(x) DEBUG1(GetName() << ": " << x)
|
||||
#define SDEBUG2(x) DEBUG2(GetName() << ": " << x)
|
||||
#define SDEBUG3(x) DEBUG3(GetName() << ": " << x)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
@@ -105,18 +105,18 @@ class MjpegServerImpl::ConnThread : public wpi::SafeThread {
|
||||
wpi::StringRef GetName() { return m_name; }
|
||||
|
||||
std::shared_ptr<SourceImpl> GetSource() {
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
return m_source;
|
||||
}
|
||||
|
||||
void StartStream() {
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
if (m_source) m_source->EnableSink();
|
||||
m_streaming = true;
|
||||
}
|
||||
|
||||
void StopStream() {
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
if (m_source) m_source->DisableSink();
|
||||
m_streaming = false;
|
||||
}
|
||||
@@ -865,7 +865,7 @@ void MjpegServerImpl::ConnThread::ProcessRequest() {
|
||||
|
||||
// worker thread for clients that connected to this server
|
||||
void MjpegServerImpl::ConnThread::Main() {
|
||||
std::unique_lock<wpi::mutex> lock(m_mutex);
|
||||
std::unique_lock lock(m_mutex);
|
||||
while (m_active) {
|
||||
while (!m_stream) {
|
||||
m_cond.wait(lock);
|
||||
@@ -898,7 +898,7 @@ void MjpegServerImpl::ServerThreadMain() {
|
||||
|
||||
auto source = GetSource();
|
||||
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
// Find unoccupied worker thread, or create one if necessary
|
||||
auto it = std::find_if(m_connThreads.begin(), m_connThreads.end(),
|
||||
[](const wpi::SafeThreadOwner<ConnThread>& owner) {
|
||||
@@ -937,7 +937,7 @@ void MjpegServerImpl::ServerThreadMain() {
|
||||
}
|
||||
|
||||
void MjpegServerImpl::SetSourceImpl(std::shared_ptr<SourceImpl> source) {
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
for (auto& connThread : m_connThreads) {
|
||||
if (auto thr = connThread.GetThread()) {
|
||||
if (thr->m_source != source) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2015-2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2015-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
@@ -102,7 +102,7 @@ void Notifier::Stop() { m_owner.Stop(); }
|
||||
void Notifier::Thread::Main() {
|
||||
if (m_on_start) m_on_start();
|
||||
|
||||
std::unique_lock<wpi::mutex> lock(m_mutex);
|
||||
std::unique_lock lock(m_mutex);
|
||||
while (m_active) {
|
||||
while (m_notifications.empty()) {
|
||||
m_cond.wait(lock);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
@@ -18,7 +18,7 @@ int PropertyContainer::GetPropertyIndex(const wpi::Twine& name) const {
|
||||
// We can't fail, so instead we create a new index if caching fails.
|
||||
CS_Status status = 0;
|
||||
if (!m_properties_cached) CacheProperties(&status);
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
wpi::SmallVector<char, 64> nameBuf;
|
||||
int& ndx = m_properties[name.toStringRef(nameBuf)];
|
||||
if (ndx == 0) {
|
||||
@@ -33,7 +33,7 @@ wpi::ArrayRef<int> PropertyContainer::EnumerateProperties(
|
||||
wpi::SmallVectorImpl<int>& vec, CS_Status* status) const {
|
||||
if (!m_properties_cached && !CacheProperties(status))
|
||||
return wpi::ArrayRef<int>{};
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
for (int i = 0; i < static_cast<int>(m_propertyData.size()); ++i) {
|
||||
if (m_propertyData[i]) vec.push_back(i + 1);
|
||||
}
|
||||
@@ -43,7 +43,7 @@ wpi::ArrayRef<int> PropertyContainer::EnumerateProperties(
|
||||
CS_PropertyKind PropertyContainer::GetPropertyKind(int property) const {
|
||||
CS_Status status = 0;
|
||||
if (!m_properties_cached && !CacheProperties(&status)) return CS_PROP_NONE;
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
auto prop = GetProperty(property);
|
||||
if (!prop) return CS_PROP_NONE;
|
||||
return prop->propKind;
|
||||
@@ -52,7 +52,7 @@ CS_PropertyKind PropertyContainer::GetPropertyKind(int property) const {
|
||||
wpi::StringRef PropertyContainer::GetPropertyName(
|
||||
int property, wpi::SmallVectorImpl<char>& buf, CS_Status* status) const {
|
||||
if (!m_properties_cached && !CacheProperties(status)) return wpi::StringRef{};
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
auto prop = GetProperty(property);
|
||||
if (!prop) {
|
||||
*status = CS_INVALID_PROPERTY;
|
||||
@@ -64,7 +64,7 @@ wpi::StringRef PropertyContainer::GetPropertyName(
|
||||
|
||||
int PropertyContainer::GetProperty(int property, CS_Status* status) const {
|
||||
if (!m_properties_cached && !CacheProperties(status)) return 0;
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
auto prop = GetProperty(property);
|
||||
if (!prop) {
|
||||
*status = CS_INVALID_PROPERTY;
|
||||
@@ -80,7 +80,7 @@ int PropertyContainer::GetProperty(int property, CS_Status* status) const {
|
||||
|
||||
void PropertyContainer::SetProperty(int property, int value,
|
||||
CS_Status* status) {
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
auto prop = GetProperty(property);
|
||||
if (!prop) {
|
||||
*status = CS_INVALID_PROPERTY;
|
||||
@@ -101,7 +101,7 @@ void PropertyContainer::SetProperty(int property, int value,
|
||||
|
||||
int PropertyContainer::GetPropertyMin(int property, CS_Status* status) const {
|
||||
if (!m_properties_cached && !CacheProperties(status)) return 0;
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
auto prop = GetProperty(property);
|
||||
if (!prop) {
|
||||
*status = CS_INVALID_PROPERTY;
|
||||
@@ -112,7 +112,7 @@ int PropertyContainer::GetPropertyMin(int property, CS_Status* status) const {
|
||||
|
||||
int PropertyContainer::GetPropertyMax(int property, CS_Status* status) const {
|
||||
if (!m_properties_cached && !CacheProperties(status)) return 0;
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
auto prop = GetProperty(property);
|
||||
if (!prop) {
|
||||
*status = CS_INVALID_PROPERTY;
|
||||
@@ -123,7 +123,7 @@ int PropertyContainer::GetPropertyMax(int property, CS_Status* status) const {
|
||||
|
||||
int PropertyContainer::GetPropertyStep(int property, CS_Status* status) const {
|
||||
if (!m_properties_cached && !CacheProperties(status)) return 0;
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
auto prop = GetProperty(property);
|
||||
if (!prop) {
|
||||
*status = CS_INVALID_PROPERTY;
|
||||
@@ -135,7 +135,7 @@ int PropertyContainer::GetPropertyStep(int property, CS_Status* status) const {
|
||||
int PropertyContainer::GetPropertyDefault(int property,
|
||||
CS_Status* status) const {
|
||||
if (!m_properties_cached && !CacheProperties(status)) return 0;
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
auto prop = GetProperty(property);
|
||||
if (!prop) {
|
||||
*status = CS_INVALID_PROPERTY;
|
||||
@@ -147,7 +147,7 @@ int PropertyContainer::GetPropertyDefault(int property,
|
||||
wpi::StringRef PropertyContainer::GetStringProperty(
|
||||
int property, wpi::SmallVectorImpl<char>& buf, CS_Status* status) const {
|
||||
if (!m_properties_cached && !CacheProperties(status)) return wpi::StringRef{};
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
auto prop = GetProperty(property);
|
||||
if (!prop) {
|
||||
*status = CS_INVALID_PROPERTY;
|
||||
@@ -164,7 +164,7 @@ wpi::StringRef PropertyContainer::GetStringProperty(
|
||||
|
||||
void PropertyContainer::SetStringProperty(int property, const wpi::Twine& value,
|
||||
CS_Status* status) {
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
auto prop = GetProperty(property);
|
||||
if (!prop) {
|
||||
*status = CS_INVALID_PROPERTY;
|
||||
@@ -186,7 +186,7 @@ std::vector<std::string> PropertyContainer::GetEnumPropertyChoices(
|
||||
int property, CS_Status* status) const {
|
||||
if (!m_properties_cached && !CacheProperties(status))
|
||||
return std::vector<std::string>{};
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
auto prop = GetProperty(property);
|
||||
if (!prop) {
|
||||
*status = CS_INVALID_PROPERTY;
|
||||
@@ -201,7 +201,7 @@ std::vector<std::string> PropertyContainer::GetEnumPropertyChoices(
|
||||
|
||||
std::unique_ptr<PropertyImpl> PropertyContainer::CreateEmptyProperty(
|
||||
const wpi::Twine& name) const {
|
||||
return wpi::make_unique<PropertyImpl>(name);
|
||||
return std::make_unique<PropertyImpl>(name);
|
||||
}
|
||||
|
||||
bool PropertyContainer::CacheProperties(CS_Status* status) const {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
|
||||
199
cscore/src/main/native/cpp/RawSinkImpl.cpp
Normal file
199
cscore/src/main/native/cpp/RawSinkImpl.cpp
Normal file
@@ -0,0 +1,199 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "RawSinkImpl.h"
|
||||
|
||||
#include "Instance.h"
|
||||
#include "cscore.h"
|
||||
#include "cscore_raw.h"
|
||||
|
||||
using namespace cs;
|
||||
|
||||
RawSinkImpl::RawSinkImpl(const wpi::Twine& name, wpi::Logger& logger,
|
||||
Notifier& notifier, Telemetry& telemetry)
|
||||
: SinkImpl{name, logger, notifier, telemetry} {
|
||||
m_active = true;
|
||||
// m_thread = std::thread(&RawSinkImpl::ThreadMain, this);
|
||||
}
|
||||
|
||||
RawSinkImpl::RawSinkImpl(const wpi::Twine& name, wpi::Logger& logger,
|
||||
Notifier& notifier, Telemetry& telemetry,
|
||||
std::function<void(uint64_t time)> processFrame)
|
||||
: SinkImpl{name, logger, notifier, telemetry} {}
|
||||
|
||||
RawSinkImpl::~RawSinkImpl() { Stop(); }
|
||||
|
||||
void RawSinkImpl::Stop() {
|
||||
m_active = false;
|
||||
|
||||
// wake up any waiters by forcing an empty frame to be sent
|
||||
if (auto source = GetSource()) source->Wakeup();
|
||||
|
||||
// join thread
|
||||
if (m_thread.joinable()) m_thread.join();
|
||||
}
|
||||
|
||||
uint64_t RawSinkImpl::GrabFrame(CS_RawFrame& image) {
|
||||
SetEnabled(true);
|
||||
|
||||
auto source = GetSource();
|
||||
if (!source) {
|
||||
// Source disconnected; sleep for one second
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto frame = source->GetNextFrame(); // blocks
|
||||
if (!frame) {
|
||||
// Bad frame; sleep for 20 ms so we don't consume all processor time.
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(20));
|
||||
return 0; // signal error
|
||||
}
|
||||
|
||||
return GrabFrameImpl(image, frame);
|
||||
}
|
||||
|
||||
uint64_t RawSinkImpl::GrabFrame(CS_RawFrame& image, double timeout) {
|
||||
SetEnabled(true);
|
||||
|
||||
auto source = GetSource();
|
||||
if (!source) {
|
||||
// Source disconnected; sleep for one second
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto frame = source->GetNextFrame(timeout); // blocks
|
||||
if (!frame) {
|
||||
// Bad frame; sleep for 20 ms so we don't consume all processor time.
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(20));
|
||||
return 0; // signal error
|
||||
}
|
||||
|
||||
return GrabFrameImpl(image, frame);
|
||||
}
|
||||
|
||||
uint64_t RawSinkImpl::GrabFrameImpl(CS_RawFrame& rawFrame,
|
||||
Frame& incomingFrame) {
|
||||
Image* newImage = nullptr;
|
||||
|
||||
if (rawFrame.pixelFormat == CS_PixelFormat::CS_PIXFMT_UNKNOWN) {
|
||||
// Always get incoming image directly on unknown
|
||||
newImage = incomingFrame.GetExistingImage(0);
|
||||
} else {
|
||||
// Format is known, ask for it
|
||||
auto width = rawFrame.width;
|
||||
auto height = rawFrame.height;
|
||||
auto pixelFormat =
|
||||
static_cast<VideoMode::PixelFormat>(rawFrame.pixelFormat);
|
||||
if (width <= 0 || height <= 0) {
|
||||
width = incomingFrame.GetOriginalWidth();
|
||||
height = incomingFrame.GetOriginalHeight();
|
||||
}
|
||||
newImage = incomingFrame.GetImage(width, height, pixelFormat);
|
||||
}
|
||||
|
||||
if (!newImage) {
|
||||
// Shouldn't happen, but just in case...
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(20));
|
||||
return 0;
|
||||
}
|
||||
|
||||
CS_AllocateRawFrameData(&rawFrame, newImage->size());
|
||||
rawFrame.height = newImage->height;
|
||||
rawFrame.width = newImage->width;
|
||||
rawFrame.pixelFormat = newImage->pixelFormat;
|
||||
rawFrame.totalData = newImage->size();
|
||||
std::copy(newImage->data(), newImage->data() + rawFrame.totalData,
|
||||
rawFrame.data);
|
||||
|
||||
return incomingFrame.GetTime();
|
||||
}
|
||||
|
||||
// Send HTTP response and a stream of JPG-frames
|
||||
void RawSinkImpl::ThreadMain() {
|
||||
Enable();
|
||||
while (m_active) {
|
||||
auto source = GetSource();
|
||||
if (!source) {
|
||||
// Source disconnected; sleep for one second
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
continue;
|
||||
}
|
||||
SDEBUG4("waiting for frame");
|
||||
Frame frame = source->GetNextFrame(); // blocks
|
||||
if (!m_active) break;
|
||||
if (!frame) {
|
||||
// Bad frame; sleep for 10 ms so we don't consume all processor time.
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
continue;
|
||||
}
|
||||
// TODO m_processFrame();
|
||||
}
|
||||
Disable();
|
||||
}
|
||||
|
||||
namespace cs {
|
||||
CS_Sink CreateRawSink(const wpi::Twine& name, CS_Status* status) {
|
||||
auto& inst = Instance::GetInstance();
|
||||
return inst.CreateSink(CS_SINK_RAW,
|
||||
std::make_shared<RawSinkImpl>(
|
||||
name, inst.logger, inst.notifier, inst.telemetry));
|
||||
}
|
||||
|
||||
CS_Sink CreateRawSinkCallback(const wpi::Twine& name,
|
||||
std::function<void(uint64_t time)> processFrame,
|
||||
CS_Status* status) {
|
||||
auto& inst = Instance::GetInstance();
|
||||
return inst.CreateSink(CS_SINK_RAW, std::make_shared<RawSinkImpl>(
|
||||
name, inst.logger, inst.notifier,
|
||||
inst.telemetry, processFrame));
|
||||
}
|
||||
|
||||
uint64_t GrabSinkFrame(CS_Sink sink, CS_RawFrame& image, CS_Status* status) {
|
||||
auto data = Instance::GetInstance().GetSink(sink);
|
||||
if (!data || data->kind != CS_SINK_RAW) {
|
||||
*status = CS_INVALID_HANDLE;
|
||||
return 0;
|
||||
}
|
||||
return static_cast<RawSinkImpl&>(*data->sink).GrabFrame(image);
|
||||
}
|
||||
|
||||
uint64_t GrabSinkFrameTimeout(CS_Sink sink, CS_RawFrame& image, double timeout,
|
||||
CS_Status* status) {
|
||||
auto data = Instance::GetInstance().GetSink(sink);
|
||||
if (!data || data->kind != CS_SINK_RAW) {
|
||||
*status = CS_INVALID_HANDLE;
|
||||
return 0;
|
||||
}
|
||||
return static_cast<RawSinkImpl&>(*data->sink).GrabFrame(image, timeout);
|
||||
}
|
||||
} // namespace cs
|
||||
|
||||
extern "C" {
|
||||
CS_Sink CS_CreateRawSink(const char* name, CS_Status* status) {
|
||||
return cs::CreateRawSink(name, status);
|
||||
}
|
||||
|
||||
CS_Sink CS_CreateRawSinkCallback(const char* name, void* data,
|
||||
void (*processFrame)(void* data,
|
||||
uint64_t time),
|
||||
CS_Status* status) {
|
||||
return cs::CreateRawSinkCallback(
|
||||
name, [=](uint64_t time) { processFrame(data, time); }, status);
|
||||
}
|
||||
|
||||
uint64_t CS_GrabRawSinkFrame(CS_Sink sink, struct CS_RawFrame* image,
|
||||
CS_Status* status) {
|
||||
return cs::GrabSinkFrame(sink, *image, status);
|
||||
}
|
||||
|
||||
uint64_t CS_GrabRawSinkFrameTimeout(CS_Sink sink, struct CS_RawFrame* image,
|
||||
double timeout, CS_Status* status) {
|
||||
return cs::GrabSinkFrameTimeout(sink, *image, timeout, status);
|
||||
}
|
||||
} // extern "C"
|
||||
52
cscore/src/main/native/cpp/RawSinkImpl.h
Normal file
52
cscore/src/main/native/cpp/RawSinkImpl.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef CSCORE_RAWSINKIMPL_H_
|
||||
#define CSCORE_RAWSINKIMPL_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#include <thread>
|
||||
|
||||
#include <wpi/Twine.h>
|
||||
#include <wpi/condition_variable.h>
|
||||
|
||||
#include "Frame.h"
|
||||
#include "SinkImpl.h"
|
||||
#include "cscore_raw.h"
|
||||
|
||||
namespace cs {
|
||||
class SourceImpl;
|
||||
|
||||
class RawSinkImpl : public SinkImpl {
|
||||
public:
|
||||
RawSinkImpl(const wpi::Twine& name, wpi::Logger& logger, Notifier& notifier,
|
||||
Telemetry& telemetry);
|
||||
RawSinkImpl(const wpi::Twine& name, wpi::Logger& logger, Notifier& notifier,
|
||||
Telemetry& telemetry,
|
||||
std::function<void(uint64_t time)> processFrame);
|
||||
~RawSinkImpl() override;
|
||||
|
||||
void Stop();
|
||||
|
||||
uint64_t GrabFrame(CS_RawFrame& frame);
|
||||
uint64_t GrabFrame(CS_RawFrame& frame, double timeout);
|
||||
|
||||
private:
|
||||
void ThreadMain();
|
||||
|
||||
uint64_t GrabFrameImpl(CS_RawFrame& rawFrame, Frame& incomingFrame);
|
||||
|
||||
std::atomic_bool m_active; // set to false to terminate threads
|
||||
std::thread m_thread;
|
||||
std::function<void(uint64_t time)> m_processFrame;
|
||||
};
|
||||
} // namespace cs
|
||||
|
||||
#endif // CSCORE_RAWSINKIMPL_H_
|
||||
83
cscore/src/main/native/cpp/RawSourceImpl.cpp
Normal file
83
cscore/src/main/native/cpp/RawSourceImpl.cpp
Normal file
@@ -0,0 +1,83 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "RawSourceImpl.h"
|
||||
|
||||
#include <wpi/timestamp.h>
|
||||
|
||||
#include "Handle.h"
|
||||
#include "Instance.h"
|
||||
#include "Log.h"
|
||||
#include "Notifier.h"
|
||||
#include "cscore_raw.h"
|
||||
|
||||
using namespace cs;
|
||||
|
||||
RawSourceImpl::RawSourceImpl(const wpi::Twine& name, wpi::Logger& logger,
|
||||
Notifier& notifier, Telemetry& telemetry,
|
||||
const VideoMode& mode)
|
||||
: ConfigurableSourceImpl{name, logger, notifier, telemetry, mode} {}
|
||||
|
||||
RawSourceImpl::~RawSourceImpl() {}
|
||||
|
||||
void RawSourceImpl::PutFrame(const CS_RawFrame& image) {
|
||||
int type;
|
||||
switch (image.pixelFormat) {
|
||||
case VideoMode::kYUYV:
|
||||
case VideoMode::kRGB565:
|
||||
type = CV_8UC2;
|
||||
break;
|
||||
case VideoMode::kBGR:
|
||||
type = CV_8UC3;
|
||||
break;
|
||||
case VideoMode::kGray:
|
||||
case VideoMode::kMJPEG:
|
||||
default:
|
||||
type = CV_8UC1;
|
||||
break;
|
||||
}
|
||||
cv::Mat finalImage{image.height, image.width, type, image.data};
|
||||
std::unique_ptr<Image> dest =
|
||||
AllocImage(static_cast<VideoMode::PixelFormat>(image.pixelFormat),
|
||||
image.width, image.height, image.totalData);
|
||||
finalImage.copyTo(dest->AsMat());
|
||||
|
||||
SourceImpl::PutFrame(std::move(dest), wpi::Now());
|
||||
}
|
||||
|
||||
namespace cs {
|
||||
CS_Source CreateRawSource(const wpi::Twine& name, const VideoMode& mode,
|
||||
CS_Status* status) {
|
||||
auto& inst = Instance::GetInstance();
|
||||
return inst.CreateSource(CS_SOURCE_RAW, std::make_shared<RawSourceImpl>(
|
||||
name, inst.logger, inst.notifier,
|
||||
inst.telemetry, mode));
|
||||
}
|
||||
|
||||
void PutSourceFrame(CS_Source source, const CS_RawFrame& image,
|
||||
CS_Status* status) {
|
||||
auto data = Instance::GetInstance().GetSource(source);
|
||||
if (!data || data->kind != CS_SOURCE_RAW) {
|
||||
*status = CS_INVALID_HANDLE;
|
||||
return;
|
||||
}
|
||||
static_cast<RawSourceImpl&>(*data->source).PutFrame(image);
|
||||
}
|
||||
} // namespace cs
|
||||
|
||||
extern "C" {
|
||||
CS_Source CS_CreateRawSource(const char* name, const CS_VideoMode* mode,
|
||||
CS_Status* status) {
|
||||
return cs::CreateRawSource(name, static_cast<const cs::VideoMode&>(*mode),
|
||||
status);
|
||||
}
|
||||
|
||||
void CS_PutRawSourceFrame(CS_Source source, const struct CS_RawFrame* image,
|
||||
CS_Status* status) {
|
||||
return cs::PutSourceFrame(source, *image, status);
|
||||
}
|
||||
} // extern "C"
|
||||
41
cscore/src/main/native/cpp/RawSourceImpl.h
Normal file
41
cscore/src/main/native/cpp/RawSourceImpl.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef CSCORE_RAWSOURCEIMPL_H_
|
||||
#define CSCORE_RAWSOURCEIMPL_H_
|
||||
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <wpi/ArrayRef.h>
|
||||
#include <wpi/Twine.h>
|
||||
|
||||
#include "ConfigurableSourceImpl.h"
|
||||
#include "SourceImpl.h"
|
||||
#include "cscore_raw.h"
|
||||
|
||||
namespace cs {
|
||||
|
||||
class RawSourceImpl : public ConfigurableSourceImpl {
|
||||
public:
|
||||
RawSourceImpl(const wpi::Twine& name, wpi::Logger& logger, Notifier& notifier,
|
||||
Telemetry& telemetry, const VideoMode& mode);
|
||||
~RawSourceImpl() override;
|
||||
|
||||
// Raw-specific functions
|
||||
void PutFrame(const CS_RawFrame& image);
|
||||
|
||||
private:
|
||||
std::atomic_bool m_connected{true};
|
||||
};
|
||||
|
||||
} // namespace cs
|
||||
|
||||
#endif // CSCORE_RAWSOURCEIMPL_H_
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
@@ -30,18 +30,18 @@ SinkImpl::~SinkImpl() {
|
||||
}
|
||||
|
||||
void SinkImpl::SetDescription(const wpi::Twine& description) {
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
m_description = description.str();
|
||||
}
|
||||
|
||||
wpi::StringRef SinkImpl::GetDescription(wpi::SmallVectorImpl<char>& buf) const {
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
buf.append(m_description.begin(), m_description.end());
|
||||
return wpi::StringRef{buf.data(), buf.size()};
|
||||
}
|
||||
|
||||
void SinkImpl::Enable() {
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
++m_enabledCount;
|
||||
if (m_enabledCount == 1) {
|
||||
if (m_source) m_source->EnableSink();
|
||||
@@ -50,7 +50,7 @@ void SinkImpl::Enable() {
|
||||
}
|
||||
|
||||
void SinkImpl::Disable() {
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
--m_enabledCount;
|
||||
if (m_enabledCount == 0) {
|
||||
if (m_source) m_source->DisableSink();
|
||||
@@ -59,7 +59,7 @@ void SinkImpl::Disable() {
|
||||
}
|
||||
|
||||
void SinkImpl::SetEnabled(bool enabled) {
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
if (enabled && m_enabledCount == 0) {
|
||||
if (m_source) m_source->EnableSink();
|
||||
m_enabledCount = 1;
|
||||
@@ -73,7 +73,7 @@ void SinkImpl::SetEnabled(bool enabled) {
|
||||
|
||||
void SinkImpl::SetSource(std::shared_ptr<SourceImpl> source) {
|
||||
{
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
if (m_source == source) return;
|
||||
if (m_source) {
|
||||
if (m_enabledCount > 0) m_source->DisableSink();
|
||||
@@ -89,13 +89,13 @@ void SinkImpl::SetSource(std::shared_ptr<SourceImpl> source) {
|
||||
}
|
||||
|
||||
std::string SinkImpl::GetError() const {
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
if (!m_source) return "no source connected";
|
||||
return m_source->GetCurFrame().GetError();
|
||||
}
|
||||
|
||||
wpi::StringRef SinkImpl::GetError(wpi::SmallVectorImpl<char>& buf) const {
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
if (!m_source) return "no source connected";
|
||||
// Make a copy as it's shared data
|
||||
wpi::StringRef error = m_source->GetCurFrame().GetError();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
@@ -48,7 +48,7 @@ class SinkImpl : public PropertyContainer {
|
||||
void SetSource(std::shared_ptr<SourceImpl> source);
|
||||
|
||||
std::shared_ptr<SourceImpl> GetSource() const {
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
return m_source;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
@@ -10,7 +10,6 @@
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
#include <wpi/STLExtras.h>
|
||||
#include <wpi/json.h>
|
||||
#include <wpi/timestamp.h>
|
||||
|
||||
@@ -45,13 +44,13 @@ SourceImpl::~SourceImpl() {
|
||||
}
|
||||
|
||||
void SourceImpl::SetDescription(const wpi::Twine& description) {
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
m_description = description.str();
|
||||
}
|
||||
|
||||
wpi::StringRef SourceImpl::GetDescription(
|
||||
wpi::SmallVectorImpl<char>& buf) const {
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
buf.append(m_description.begin(), m_description.end());
|
||||
return wpi::StringRef{buf.data(), buf.size()};
|
||||
}
|
||||
@@ -65,24 +64,24 @@ void SourceImpl::SetConnected(bool connected) {
|
||||
}
|
||||
|
||||
uint64_t SourceImpl::GetCurFrameTime() {
|
||||
std::unique_lock<wpi::mutex> lock{m_frameMutex};
|
||||
std::unique_lock lock{m_frameMutex};
|
||||
return m_frame.GetTime();
|
||||
}
|
||||
|
||||
Frame SourceImpl::GetCurFrame() {
|
||||
std::unique_lock<wpi::mutex> lock{m_frameMutex};
|
||||
std::unique_lock lock{m_frameMutex};
|
||||
return m_frame;
|
||||
}
|
||||
|
||||
Frame SourceImpl::GetNextFrame() {
|
||||
std::unique_lock<wpi::mutex> lock{m_frameMutex};
|
||||
std::unique_lock lock{m_frameMutex};
|
||||
auto oldTime = m_frame.GetTime();
|
||||
m_frameCv.wait(lock, [=] { return m_frame.GetTime() != oldTime; });
|
||||
return m_frame;
|
||||
}
|
||||
|
||||
Frame SourceImpl::GetNextFrame(double timeout) {
|
||||
std::unique_lock<wpi::mutex> lock{m_frameMutex};
|
||||
std::unique_lock lock{m_frameMutex};
|
||||
auto oldTime = m_frame.GetTime();
|
||||
if (!m_frameCv.wait_for(
|
||||
lock, std::chrono::milliseconds(static_cast<int>(timeout * 1000)),
|
||||
@@ -94,7 +93,7 @@ Frame SourceImpl::GetNextFrame(double timeout) {
|
||||
|
||||
void SourceImpl::Wakeup() {
|
||||
{
|
||||
std::lock_guard<wpi::mutex> lock{m_frameMutex};
|
||||
std::scoped_lock lock{m_frameMutex};
|
||||
m_frame = Frame{*this, wpi::StringRef{}, 0};
|
||||
}
|
||||
m_frameCv.notify_all();
|
||||
@@ -135,7 +134,7 @@ void SourceImpl::SetExposureManual(int value, CS_Status* status) {
|
||||
|
||||
VideoMode SourceImpl::GetVideoMode(CS_Status* status) const {
|
||||
if (!m_properties_cached && !CacheProperties(status)) return VideoMode{};
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
return m_mode;
|
||||
}
|
||||
|
||||
@@ -381,7 +380,7 @@ std::vector<VideoMode> SourceImpl::EnumerateVideoModes(
|
||||
CS_Status* status) const {
|
||||
if (!m_properties_cached && !CacheProperties(status))
|
||||
return std::vector<VideoMode>{};
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
return m_videoModes;
|
||||
}
|
||||
|
||||
@@ -389,7 +388,7 @@ std::unique_ptr<Image> SourceImpl::AllocImage(
|
||||
VideoMode::PixelFormat pixelFormat, int width, int height, size_t size) {
|
||||
std::unique_ptr<Image> image;
|
||||
{
|
||||
std::lock_guard<wpi::mutex> lock{m_poolMutex};
|
||||
std::scoped_lock lock{m_poolMutex};
|
||||
// find the smallest existing frame that is at least big enough.
|
||||
int found = -1;
|
||||
for (size_t i = 0; i < m_imagesAvail.size(); ++i) {
|
||||
@@ -441,7 +440,7 @@ void SourceImpl::PutFrame(std::unique_ptr<Image> image, Frame::Time time) {
|
||||
|
||||
// Update frame
|
||||
{
|
||||
std::lock_guard<wpi::mutex> lock{m_frameMutex};
|
||||
std::scoped_lock lock{m_frameMutex};
|
||||
m_frame = Frame{*this, std::move(image), time};
|
||||
}
|
||||
|
||||
@@ -452,7 +451,7 @@ void SourceImpl::PutFrame(std::unique_ptr<Image> image, Frame::Time time) {
|
||||
void SourceImpl::PutError(const wpi::Twine& msg, Frame::Time time) {
|
||||
// Update frame
|
||||
{
|
||||
std::lock_guard<wpi::mutex> lock{m_frameMutex};
|
||||
std::scoped_lock lock{m_frameMutex};
|
||||
m_frame = Frame{*this, msg, time};
|
||||
}
|
||||
|
||||
@@ -490,7 +489,7 @@ void SourceImpl::UpdatePropertyValue(int property, bool setString, int value,
|
||||
}
|
||||
|
||||
void SourceImpl::ReleaseImage(std::unique_ptr<Image> image) {
|
||||
std::lock_guard<wpi::mutex> lock{m_poolMutex};
|
||||
std::scoped_lock lock{m_poolMutex};
|
||||
if (m_destroyFrames) return;
|
||||
// Return the frame to the pool. First try to find an empty slot, otherwise
|
||||
// add it to the end.
|
||||
@@ -512,9 +511,9 @@ void SourceImpl::ReleaseImage(std::unique_ptr<Image> image) {
|
||||
}
|
||||
|
||||
std::unique_ptr<Frame::Impl> SourceImpl::AllocFrameImpl() {
|
||||
std::lock_guard<wpi::mutex> lock{m_poolMutex};
|
||||
std::scoped_lock lock{m_poolMutex};
|
||||
|
||||
if (m_framesAvail.empty()) return wpi::make_unique<Frame::Impl>(*this);
|
||||
if (m_framesAvail.empty()) return std::make_unique<Frame::Impl>(*this);
|
||||
|
||||
auto impl = std::move(m_framesAvail.back());
|
||||
m_framesAvail.pop_back();
|
||||
@@ -522,7 +521,7 @@ std::unique_ptr<Frame::Impl> SourceImpl::AllocFrameImpl() {
|
||||
}
|
||||
|
||||
void SourceImpl::ReleaseFrameImpl(std::unique_ptr<Frame::Impl> impl) {
|
||||
std::lock_guard<wpi::mutex> lock{m_poolMutex};
|
||||
std::scoped_lock lock{m_poolMutex};
|
||||
if (m_destroyFrames) return;
|
||||
m_framesAvail.push_back(std::move(impl));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2015-2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2015-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
@@ -53,7 +53,7 @@ void Telemetry::Start() { m_owner.Start(m_notifier); }
|
||||
void Telemetry::Stop() { m_owner.Stop(); }
|
||||
|
||||
void Telemetry::Thread::Main() {
|
||||
std::unique_lock<wpi::mutex> lock(m_mutex);
|
||||
std::unique_lock lock(m_mutex);
|
||||
auto prevTime = std::chrono::steady_clock::now();
|
||||
while (m_active) {
|
||||
double period = m_period;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
@@ -78,7 +78,11 @@ template <typename THandle, typename TStruct, int typeValue, typename TMutex>
|
||||
template <typename... Args>
|
||||
THandle UnlimitedHandleResource<THandle, TStruct, typeValue, TMutex>::Allocate(
|
||||
Args&&... args) {
|
||||
std::lock_guard<TMutex> sync(m_handleMutex);
|
||||
#ifdef _MSC_VER // work around VS2019 16.4.0 bug
|
||||
std::scoped_lock<TMutex> lock(m_handleMutex);
|
||||
#else
|
||||
std::scoped_lock sync(m_handleMutex);
|
||||
#endif
|
||||
size_t i;
|
||||
for (i = 0; i < m_structures.size(); i++) {
|
||||
if (m_structures[i] == nullptr) {
|
||||
@@ -96,7 +100,7 @@ THandle UnlimitedHandleResource<THandle, TStruct, typeValue, TMutex>::Allocate(
|
||||
template <typename THandle, typename TStruct, int typeValue, typename TMutex>
|
||||
THandle UnlimitedHandleResource<THandle, TStruct, typeValue, TMutex>::Allocate(
|
||||
std::shared_ptr<THandle> structure) {
|
||||
std::lock_guard<TMutex> sync(m_handleMutex);
|
||||
std::scoped_lock sync(m_handleMutex);
|
||||
size_t i;
|
||||
for (i = 0; i < m_structures.size(); i++) {
|
||||
if (m_structures[i] == nullptr) {
|
||||
@@ -117,7 +121,7 @@ UnlimitedHandleResource<THandle, TStruct, typeValue, TMutex>::Get(
|
||||
auto index =
|
||||
handle.GetTypedIndex(static_cast<typename THandle::Type>(typeValue));
|
||||
if (index < 0) return nullptr;
|
||||
std::lock_guard<TMutex> sync(m_handleMutex);
|
||||
std::scoped_lock sync(m_handleMutex);
|
||||
if (index >= static_cast<int>(m_structures.size())) return nullptr;
|
||||
return m_structures[index];
|
||||
}
|
||||
@@ -129,7 +133,7 @@ UnlimitedHandleResource<THandle, TStruct, typeValue, TMutex>::Free(
|
||||
auto index =
|
||||
handle.GetTypedIndex(static_cast<typename THandle::Type>(typeValue));
|
||||
if (index < 0) return nullptr;
|
||||
std::lock_guard<TMutex> sync(m_handleMutex);
|
||||
std::scoped_lock sync(m_handleMutex);
|
||||
if (index >= static_cast<int>(m_structures.size())) return nullptr;
|
||||
auto rv = std::move(m_structures[index]);
|
||||
m_structures[index].reset();
|
||||
@@ -148,7 +152,7 @@ UnlimitedHandleResource<THandle, TStruct, typeValue, TMutex>::GetAll(
|
||||
template <typename THandle, typename TStruct, int typeValue, typename TMutex>
|
||||
inline std::vector<std::shared_ptr<TStruct>>
|
||||
UnlimitedHandleResource<THandle, TStruct, typeValue, TMutex>::FreeAll() {
|
||||
std::lock_guard<TMutex> sync(m_handleMutex);
|
||||
std::scoped_lock sync(m_handleMutex);
|
||||
auto rv = std::move(m_structures);
|
||||
m_structures.clear();
|
||||
return rv;
|
||||
@@ -158,7 +162,7 @@ template <typename THandle, typename TStruct, int typeValue, typename TMutex>
|
||||
template <typename F>
|
||||
inline void
|
||||
UnlimitedHandleResource<THandle, TStruct, typeValue, TMutex>::ForEach(F func) {
|
||||
std::lock_guard<TMutex> sync(m_handleMutex);
|
||||
std::scoped_lock sync(m_handleMutex);
|
||||
for (size_t i = 0; i < m_structures.size(); i++) {
|
||||
if (m_structures[i] != nullptr) func(MakeHandle(i), *(m_structures[i]));
|
||||
}
|
||||
@@ -168,7 +172,7 @@ template <typename THandle, typename TStruct, int typeValue, typename TMutex>
|
||||
template <typename F>
|
||||
inline std::pair<THandle, std::shared_ptr<TStruct>>
|
||||
UnlimitedHandleResource<THandle, TStruct, typeValue, TMutex>::FindIf(F func) {
|
||||
std::lock_guard<TMutex> sync(m_handleMutex);
|
||||
std::scoped_lock sync(m_handleMutex);
|
||||
for (size_t i = 0; i < m_structures.size(); i++) {
|
||||
auto& structure = m_structures[i];
|
||||
if (structure != nullptr && func(*structure))
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
@@ -17,10 +17,12 @@ static void ConvertToC(CS_UsbCameraInfo* out, const UsbCameraInfo& in) {
|
||||
out->path = ConvertToC(in.path);
|
||||
out->name = ConvertToC(in.name);
|
||||
out->otherPaths = static_cast<char**>(
|
||||
wpi::CheckedMalloc(in.otherPaths.size() * sizeof(char*)));
|
||||
wpi::safe_malloc(in.otherPaths.size() * sizeof(char*)));
|
||||
out->otherPathsCount = in.otherPaths.size();
|
||||
for (size_t i = 0; i < in.otherPaths.size(); ++i)
|
||||
out->otherPaths[i] = cs::ConvertToC(in.otherPaths[i]);
|
||||
out->vendorId = in.vendorId;
|
||||
out->productId = in.productId;
|
||||
}
|
||||
|
||||
static void FreeUsbCameraInfo(CS_UsbCameraInfo* info) {
|
||||
@@ -50,7 +52,7 @@ CS_UsbCameraInfo* CS_GetUsbCameraInfo(CS_Source source, CS_Status* status) {
|
||||
auto info = cs::GetUsbCameraInfo(source, status);
|
||||
if (*status != CS_OK) return nullptr;
|
||||
CS_UsbCameraInfo* out = static_cast<CS_UsbCameraInfo*>(
|
||||
wpi::CheckedMalloc(sizeof(CS_UsbCameraInfo)));
|
||||
wpi::safe_malloc(sizeof(CS_UsbCameraInfo)));
|
||||
ConvertToC(out, info);
|
||||
return out;
|
||||
}
|
||||
@@ -58,7 +60,7 @@ CS_UsbCameraInfo* CS_GetUsbCameraInfo(CS_Source source, CS_Status* status) {
|
||||
CS_UsbCameraInfo* CS_EnumerateUsbCameras(int* count, CS_Status* status) {
|
||||
auto cameras = cs::EnumerateUsbCameras(status);
|
||||
CS_UsbCameraInfo* out = static_cast<CS_UsbCameraInfo*>(
|
||||
wpi::CheckedMalloc(cameras.size() * sizeof(CS_UsbCameraInfo)));
|
||||
wpi::safe_malloc(cameras.size() * sizeof(CS_UsbCameraInfo)));
|
||||
*count = cameras.size();
|
||||
for (size_t i = 0; i < cameras.size(); ++i) ConvertToC(&out[i], cameras[i]);
|
||||
return out;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
@@ -11,13 +11,13 @@
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include <wpi/MemAlloc.h>
|
||||
#include <wpi/StringRef.h>
|
||||
#include <wpi/memory.h>
|
||||
|
||||
namespace cs {
|
||||
|
||||
inline char* ConvertToC(wpi::StringRef in) {
|
||||
char* out = static_cast<char*>(wpi::CheckedMalloc(in.size() + 1));
|
||||
char* out = static_cast<char*>(wpi::safe_malloc(in.size() + 1));
|
||||
std::memmove(out, in.data(), in.size());
|
||||
out[in.size()] = '\0';
|
||||
return out;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
@@ -11,11 +11,12 @@
|
||||
#include <cstdlib>
|
||||
|
||||
#include <opencv2/core/core.hpp>
|
||||
#include <wpi/MemAlloc.h>
|
||||
#include <wpi/SmallString.h>
|
||||
#include <wpi/memory.h>
|
||||
|
||||
#include "c_util.h"
|
||||
#include "cscore_cpp.h"
|
||||
#include "cscore_raw.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
@@ -70,7 +71,7 @@ char** CS_GetEnumPropertyChoices(CS_Property property, int* count,
|
||||
CS_Status* status) {
|
||||
auto choices = cs::GetEnumPropertyChoices(property, status);
|
||||
char** out =
|
||||
static_cast<char**>(wpi::CheckedMalloc(choices.size() * sizeof(char*)));
|
||||
static_cast<char**>(wpi::safe_malloc(choices.size() * sizeof(char*)));
|
||||
*count = choices.size();
|
||||
for (size_t i = 0; i < choices.size(); ++i)
|
||||
out[i] = cs::ConvertToC(choices[i]);
|
||||
@@ -123,7 +124,7 @@ CS_Property* CS_EnumerateSourceProperties(CS_Source source, int* count,
|
||||
wpi::SmallVector<CS_Property, 32> buf;
|
||||
auto vec = cs::EnumerateSourceProperties(source, buf, status);
|
||||
CS_Property* out = static_cast<CS_Property*>(
|
||||
wpi::CheckedMalloc(vec.size() * sizeof(CS_Property)));
|
||||
wpi::safe_malloc(vec.size() * sizeof(CS_Property)));
|
||||
*count = vec.size();
|
||||
std::copy(vec.begin(), vec.end(), out);
|
||||
return out;
|
||||
@@ -183,7 +184,7 @@ CS_VideoMode* CS_EnumerateSourceVideoModes(CS_Source source, int* count,
|
||||
CS_Status* status) {
|
||||
auto vec = cs::EnumerateSourceVideoModes(source, status);
|
||||
CS_VideoMode* out = static_cast<CS_VideoMode*>(
|
||||
wpi::CheckedMalloc(vec.size() * sizeof(CS_VideoMode)));
|
||||
wpi::safe_malloc(vec.size() * sizeof(CS_VideoMode)));
|
||||
*count = vec.size();
|
||||
std::copy(vec.begin(), vec.end(), out);
|
||||
return out;
|
||||
@@ -193,8 +194,8 @@ CS_Sink* CS_EnumerateSourceSinks(CS_Source source, int* count,
|
||||
CS_Status* status) {
|
||||
wpi::SmallVector<CS_Sink, 32> buf;
|
||||
auto handles = cs::EnumerateSourceSinks(source, buf, status);
|
||||
CS_Sink* sinks = static_cast<CS_Sink*>(
|
||||
wpi::CheckedMalloc(handles.size() * sizeof(CS_Sink)));
|
||||
CS_Sink* sinks =
|
||||
static_cast<CS_Sink*>(wpi::safe_malloc(handles.size() * sizeof(CS_Sink)));
|
||||
*count = handles.size();
|
||||
std::copy(handles.begin(), handles.end(), sinks);
|
||||
return sinks;
|
||||
@@ -271,7 +272,7 @@ CS_Property* CS_EnumerateSinkProperties(CS_Sink sink, int* count,
|
||||
wpi::SmallVector<CS_Property, 32> buf;
|
||||
auto vec = cs::EnumerateSinkProperties(sink, buf, status);
|
||||
CS_Property* out = static_cast<CS_Property*>(
|
||||
wpi::CheckedMalloc(vec.size() * sizeof(CS_Property)));
|
||||
wpi::safe_malloc(vec.size() * sizeof(CS_Property)));
|
||||
*count = vec.size();
|
||||
std::copy(vec.begin(), vec.end(), out);
|
||||
return out;
|
||||
@@ -372,7 +373,7 @@ CS_Source* CS_EnumerateSources(int* count, CS_Status* status) {
|
||||
wpi::SmallVector<CS_Source, 32> buf;
|
||||
auto handles = cs::EnumerateSourceHandles(buf, status);
|
||||
CS_Source* sources = static_cast<CS_Source*>(
|
||||
wpi::CheckedMalloc(handles.size() * sizeof(CS_Source)));
|
||||
wpi::safe_malloc(handles.size() * sizeof(CS_Source)));
|
||||
*count = handles.size();
|
||||
std::copy(handles.begin(), handles.end(), sources);
|
||||
return sources;
|
||||
@@ -390,8 +391,8 @@ void CS_ReleaseEnumeratedSources(CS_Source* sources, int count) {
|
||||
CS_Sink* CS_EnumerateSinks(int* count, CS_Status* status) {
|
||||
wpi::SmallVector<CS_Sink, 32> buf;
|
||||
auto handles = cs::EnumerateSinkHandles(buf, status);
|
||||
CS_Sink* sinks = static_cast<CS_Sink*>(
|
||||
wpi::CheckedMalloc(handles.size() * sizeof(CS_Sink)));
|
||||
CS_Sink* sinks =
|
||||
static_cast<CS_Sink*>(wpi::safe_malloc(handles.size() * sizeof(CS_Sink)));
|
||||
*count = handles.size();
|
||||
std::copy(handles.begin(), handles.end(), sinks);
|
||||
return sinks;
|
||||
@@ -426,8 +427,8 @@ char* CS_GetHostname() { return cs::ConvertToC(cs::GetHostname()); }
|
||||
|
||||
char** CS_GetNetworkInterfaces(int* count) {
|
||||
auto interfaces = cs::GetNetworkInterfaces();
|
||||
char** out = static_cast<char**>(
|
||||
wpi::CheckedMalloc(interfaces.size() * sizeof(char*)));
|
||||
char** out =
|
||||
static_cast<char**>(wpi::safe_malloc(interfaces.size() * sizeof(char*)));
|
||||
*count = interfaces.size();
|
||||
for (size_t i = 0; i < interfaces.size(); ++i)
|
||||
out[i] = cs::ConvertToC(interfaces[i]);
|
||||
@@ -440,4 +441,23 @@ void CS_FreeNetworkInterfaces(char** interfaces, int count) {
|
||||
std::free(interfaces);
|
||||
}
|
||||
|
||||
void CS_AllocateRawFrameData(CS_RawFrame* frame, int requestedSize) {
|
||||
if (frame->dataLength >= requestedSize) return;
|
||||
if (frame->data) {
|
||||
frame->data =
|
||||
static_cast<char*>(wpi::safe_realloc(frame->data, requestedSize));
|
||||
} else {
|
||||
frame->data = static_cast<char*>(wpi::safe_malloc(requestedSize));
|
||||
}
|
||||
frame->dataLength = requestedSize;
|
||||
}
|
||||
|
||||
void CS_FreeRawFrameData(CS_RawFrame* frame) {
|
||||
if (frame->data) {
|
||||
std::free(frame->data);
|
||||
frame->data = nullptr;
|
||||
frame->dataLength = 0;
|
||||
}
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
|
||||
@@ -1,17 +1,26 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#include <exception>
|
||||
|
||||
#include <opencv2/core/core.hpp>
|
||||
#include <wpi/SmallString.h>
|
||||
#include <wpi/jni_util.h>
|
||||
#include <wpi/raw_ostream.h>
|
||||
|
||||
#include "cscore_cpp.h"
|
||||
#include "cscore_cv.h"
|
||||
#include "cscore_raw.h"
|
||||
#include "edu_wpi_cscore_CameraServerJNI.h"
|
||||
|
||||
namespace cv {
|
||||
class Mat;
|
||||
} // namespace cv
|
||||
|
||||
using namespace wpi::java;
|
||||
|
||||
//
|
||||
@@ -23,21 +32,25 @@ static JavaVM* jvm = nullptr;
|
||||
static JClass usbCameraInfoCls;
|
||||
static JClass videoModeCls;
|
||||
static JClass videoEventCls;
|
||||
static JClass rawFrameCls;
|
||||
static JException videoEx;
|
||||
static JException nullPointerEx;
|
||||
static JException unsupportedEx;
|
||||
static JException exceptionEx;
|
||||
// Thread-attached environment for listener callbacks.
|
||||
static JNIEnv* listenerEnv = nullptr;
|
||||
|
||||
static const JClassInit classes[] = {
|
||||
{"edu/wpi/cscore/UsbCameraInfo", &usbCameraInfoCls},
|
||||
{"edu/wpi/cscore/VideoMode", &videoModeCls},
|
||||
{"edu/wpi/cscore/VideoEvent", &videoEventCls}};
|
||||
{"edu/wpi/cscore/VideoEvent", &videoEventCls},
|
||||
{"edu/wpi/cscore/raw/RawFrame", &rawFrameCls}};
|
||||
|
||||
static const JExceptionInit exceptions[] = {
|
||||
{"edu/wpi/cscore/VideoException", &videoEx},
|
||||
{"java/lang/NullPointerException", &nullPointerEx},
|
||||
{"java/lang/UnsupportedOperationException", &unsupportedEx}};
|
||||
{"java/lang/UnsupportedOperationException", &unsupportedEx},
|
||||
{"java/lang/Exception", &exceptionEx}};
|
||||
|
||||
static void ListenerOnStart() {
|
||||
if (!jvm) return;
|
||||
@@ -59,6 +72,30 @@ static void ListenerOnExit() {
|
||||
jvm->DetachCurrentThread();
|
||||
}
|
||||
|
||||
/// throw java exception
|
||||
static void ThrowJavaException(JNIEnv* env, const std::exception* e) {
|
||||
wpi::SmallString<128> what;
|
||||
jclass je = 0;
|
||||
|
||||
if (e) {
|
||||
const char* exception_type = "std::exception";
|
||||
|
||||
if (dynamic_cast<const cv::Exception*>(e)) {
|
||||
exception_type = "cv::Exception";
|
||||
je = env->FindClass("org/opencv/core/CvException");
|
||||
}
|
||||
|
||||
what = exception_type;
|
||||
what += ": ";
|
||||
what += e->what();
|
||||
} else {
|
||||
what = "unknown exception";
|
||||
}
|
||||
|
||||
if (!je) je = exceptionEx;
|
||||
env->ThrowNew(je, what.c_str());
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
|
||||
@@ -186,13 +223,14 @@ static inline bool CheckStatus(JNIEnv* env, CS_Status status) {
|
||||
static jobject MakeJObject(JNIEnv* env, const cs::UsbCameraInfo& info) {
|
||||
static jmethodID constructor = env->GetMethodID(
|
||||
usbCameraInfoCls, "<init>",
|
||||
"(ILjava/lang/String;Ljava/lang/String;[Ljava/lang/String;)V");
|
||||
"(ILjava/lang/String;Ljava/lang/String;[Ljava/lang/String;II)V");
|
||||
JLocal<jstring> path(env, MakeJString(env, info.path));
|
||||
JLocal<jstring> name(env, MakeJString(env, info.name));
|
||||
JLocal<jobjectArray> otherPaths(env, MakeJStringArray(env, info.otherPaths));
|
||||
return env->NewObject(usbCameraInfoCls, constructor,
|
||||
static_cast<jint>(info.dev), path.obj(), name.obj(),
|
||||
otherPaths.obj());
|
||||
otherPaths.obj(), static_cast<jint>(info.vendorId),
|
||||
static_cast<jint>(info.productId));
|
||||
}
|
||||
|
||||
static jobject MakeJObject(JNIEnv* env, const cs::VideoMode& videoMode) {
|
||||
@@ -506,12 +544,12 @@ Java_edu_wpi_cscore_CameraServerJNI_createHttpCameraMulti
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_cscore_CameraServerJNI
|
||||
* Class: edu_wpi_cscore_CameraServerCvJNI
|
||||
* Method: createCvSource
|
||||
* Signature: (Ljava/lang/String;IIII)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_edu_wpi_cscore_CameraServerJNI_createCvSource
|
||||
Java_edu_wpi_cscore_CameraServerCvJNI_createCvSource
|
||||
(JNIEnv* env, jclass, jstring name, jint pixelFormat, jint width, jint height,
|
||||
jint fps)
|
||||
{
|
||||
@@ -530,6 +568,31 @@ Java_edu_wpi_cscore_CameraServerJNI_createCvSource
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_cscore_CameraServerJNI
|
||||
* Method: createRawSource
|
||||
* Signature: (Ljava/lang/String;IIII)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_edu_wpi_cscore_CameraServerJNI_createRawSource
|
||||
(JNIEnv* env, jclass, jstring name, jint pixelFormat, jint width, jint height,
|
||||
jint fps)
|
||||
{
|
||||
if (!name) {
|
||||
nullPointerEx.Throw(env, "name cannot be null");
|
||||
return 0;
|
||||
}
|
||||
CS_Status status = 0;
|
||||
auto val = cs::CreateRawSource(
|
||||
JStringRef{env, name}.str(),
|
||||
cs::VideoMode{static_cast<cs::VideoMode::PixelFormat>(pixelFormat),
|
||||
static_cast<int>(width), static_cast<int>(height),
|
||||
static_cast<int>(fps)},
|
||||
&status);
|
||||
CheckStatus(env, status);
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_cscore_CameraServerJNI
|
||||
* Method: getSourceKind
|
||||
@@ -1054,17 +1117,68 @@ Java_edu_wpi_cscore_CameraServerJNI_getHttpCameraUrls
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_cscore_CameraServerJNI
|
||||
* Class: edu_wpi_cscore_CameraServerCvJNI
|
||||
* Method: putSourceFrame
|
||||
* Signature: (IJ)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_cscore_CameraServerJNI_putSourceFrame
|
||||
Java_edu_wpi_cscore_CameraServerCvJNI_putSourceFrame
|
||||
(JNIEnv* env, jclass, jint source, jlong imageNativeObj)
|
||||
{
|
||||
cv::Mat& image = *((cv::Mat*)imageNativeObj);
|
||||
try {
|
||||
cv::Mat& image = *((cv::Mat*)imageNativeObj);
|
||||
CS_Status status = 0;
|
||||
cs::PutSourceFrame(source, image, &status);
|
||||
CheckStatus(env, status);
|
||||
} catch (const std::exception& e) {
|
||||
ThrowJavaException(env, &e);
|
||||
} catch (...) {
|
||||
ThrowJavaException(env, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// int width, int height, int pixelFormat, int totalData
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_cscore_CameraServerJNI
|
||||
* Method: putRawSourceFrameBB
|
||||
* Signature: (ILjava/lang/Object;IIII)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_cscore_CameraServerJNI_putRawSourceFrameBB
|
||||
(JNIEnv* env, jclass, jint source, jobject byteBuffer, jint width,
|
||||
jint height, jint pixelFormat, jint totalData)
|
||||
{
|
||||
CS_RawFrame rawFrame;
|
||||
rawFrame.data =
|
||||
reinterpret_cast<char*>(env->GetDirectBufferAddress(byteBuffer));
|
||||
rawFrame.totalData = totalData;
|
||||
rawFrame.pixelFormat = pixelFormat;
|
||||
rawFrame.width = width;
|
||||
rawFrame.height = height;
|
||||
CS_Status status = 0;
|
||||
cs::PutSourceFrame(source, image, &status);
|
||||
cs::PutSourceFrame(source, rawFrame, &status);
|
||||
CheckStatus(env, status);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_cscore_CameraServerJNI
|
||||
* Method: putRawSourceFrame
|
||||
* Signature: (IJIIII)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_cscore_CameraServerJNI_putRawSourceFrame
|
||||
(JNIEnv* env, jclass, jint source, jlong ptr, jint width, jint height,
|
||||
jint pixelFormat, jint totalData)
|
||||
{
|
||||
CS_RawFrame rawFrame;
|
||||
rawFrame.data = reinterpret_cast<char*>(static_cast<intptr_t>(ptr));
|
||||
rawFrame.totalData = totalData;
|
||||
rawFrame.pixelFormat = pixelFormat;
|
||||
rawFrame.width = width;
|
||||
rawFrame.height = height;
|
||||
CS_Status status = 0;
|
||||
cs::PutSourceFrame(source, rawFrame, &status);
|
||||
CheckStatus(env, status);
|
||||
}
|
||||
|
||||
@@ -1192,12 +1306,12 @@ Java_edu_wpi_cscore_CameraServerJNI_createMjpegServer
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_cscore_CameraServerJNI
|
||||
* Class: edu_wpi_cscore_CameraServerCvJNI
|
||||
* Method: createCvSink
|
||||
* Signature: (Ljava/lang/String;)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_edu_wpi_cscore_CameraServerJNI_createCvSink
|
||||
Java_edu_wpi_cscore_CameraServerCvJNI_createCvSink
|
||||
(JNIEnv* env, jclass, jstring name)
|
||||
{
|
||||
if (!name) {
|
||||
@@ -1210,6 +1324,25 @@ Java_edu_wpi_cscore_CameraServerJNI_createCvSink
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_cscore_CameraServerJNI
|
||||
* Method: createRawSink
|
||||
* Signature: (Ljava/lang/String;)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_edu_wpi_cscore_CameraServerJNI_createRawSink
|
||||
(JNIEnv* env, jclass, jstring name)
|
||||
{
|
||||
if (!name) {
|
||||
nullPointerEx.Throw(env, "name cannot be null");
|
||||
return 0;
|
||||
}
|
||||
CS_Status status = 0;
|
||||
auto val = cs::CreateRawSink(JStringRef{env, name}.str(), &status);
|
||||
CheckStatus(env, status);
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_cscore_CameraServerJNI
|
||||
* Method: getSinkKind
|
||||
@@ -1449,34 +1582,119 @@ Java_edu_wpi_cscore_CameraServerJNI_setSinkDescription
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_cscore_CameraServerJNI
|
||||
* Class: edu_wpi_cscore_CameraServerCvJNI
|
||||
* Method: grabSinkFrame
|
||||
* Signature: (IJ)J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_edu_wpi_cscore_CameraServerJNI_grabSinkFrame
|
||||
Java_edu_wpi_cscore_CameraServerCvJNI_grabSinkFrame
|
||||
(JNIEnv* env, jclass, jint sink, jlong imageNativeObj)
|
||||
{
|
||||
cv::Mat& image = *((cv::Mat*)imageNativeObj);
|
||||
try {
|
||||
cv::Mat& image = *((cv::Mat*)imageNativeObj);
|
||||
CS_Status status = 0;
|
||||
auto rv = cs::GrabSinkFrame(sink, image, &status);
|
||||
CheckStatus(env, status);
|
||||
return rv;
|
||||
} catch (const std::exception& e) {
|
||||
ThrowJavaException(env, &e);
|
||||
return 0;
|
||||
} catch (...) {
|
||||
ThrowJavaException(env, 0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_cscore_CameraServerCvJNI
|
||||
* Method: grabSinkFrameTimeout
|
||||
* Signature: (IJD)J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_edu_wpi_cscore_CameraServerCvJNI_grabSinkFrameTimeout
|
||||
(JNIEnv* env, jclass, jint sink, jlong imageNativeObj, jdouble timeout)
|
||||
{
|
||||
try {
|
||||
cv::Mat& image = *((cv::Mat*)imageNativeObj);
|
||||
CS_Status status = 0;
|
||||
auto rv = cs::GrabSinkFrameTimeout(sink, image, timeout, &status);
|
||||
CheckStatus(env, status);
|
||||
return rv;
|
||||
} catch (const std::exception& e) {
|
||||
ThrowJavaException(env, &e);
|
||||
return 0;
|
||||
} catch (...) {
|
||||
ThrowJavaException(env, 0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void SetRawFrameData(JNIEnv* env, jobject rawFrameObj,
|
||||
jobject byteBuffer, bool didChangeDataPtr,
|
||||
const CS_RawFrame& frame) {
|
||||
static jmethodID setMethod =
|
||||
env->GetMethodID(rawFrameCls, "setData", "(Ljava/nio/ByteBuffer;JIIII)V");
|
||||
jlong framePtr = static_cast<jlong>(reinterpret_cast<intptr_t>(frame.data));
|
||||
|
||||
if (didChangeDataPtr) {
|
||||
byteBuffer = env->NewDirectByteBuffer(frame.data, frame.dataLength);
|
||||
}
|
||||
|
||||
env->CallVoidMethod(
|
||||
rawFrameObj, setMethod, byteBuffer, framePtr,
|
||||
static_cast<jint>(frame.totalData), static_cast<jint>(frame.width),
|
||||
static_cast<jint>(frame.height), static_cast<jint>(frame.pixelFormat));
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_cscore_CameraServerJNI
|
||||
* Method: grabRawSinkFrameImpl
|
||||
* Signature: (ILjava/lang/Object;JLjava/lang/Object;III)J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_edu_wpi_cscore_CameraServerJNI_grabRawSinkFrameImpl
|
||||
(JNIEnv* env, jclass, jint sink, jobject rawFrameObj, jlong rawFramePtr,
|
||||
jobject byteBuffer, jint width, jint height, jint pixelFormat)
|
||||
{
|
||||
CS_RawFrame* ptr =
|
||||
reinterpret_cast<CS_RawFrame*>(static_cast<intptr_t>(rawFramePtr));
|
||||
auto origDataPtr = ptr->data;
|
||||
ptr->width = width;
|
||||
ptr->height = height;
|
||||
ptr->pixelFormat = pixelFormat;
|
||||
CS_Status status = 0;
|
||||
auto rv = cs::GrabSinkFrame(sink, image, &status);
|
||||
CheckStatus(env, status);
|
||||
auto rv = cs::GrabSinkFrame(static_cast<CS_Sink>(sink), *ptr, &status);
|
||||
if (!CheckStatus(env, status)) {
|
||||
return 0;
|
||||
}
|
||||
SetRawFrameData(env, rawFrameObj, byteBuffer, origDataPtr != ptr->data, *ptr);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_cscore_CameraServerJNI
|
||||
* Method: grabSinkFrameTimeout
|
||||
* Signature: (IJD)J
|
||||
* Method: grabRawSinkFrameTimeoutImpl
|
||||
* Signature: (ILjava/lang/Object;JLjava/lang/Object;IIID)J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_edu_wpi_cscore_CameraServerJNI_grabSinkFrameTimeout
|
||||
(JNIEnv* env, jclass, jint sink, jlong imageNativeObj, jdouble timeout)
|
||||
Java_edu_wpi_cscore_CameraServerJNI_grabRawSinkFrameTimeoutImpl
|
||||
(JNIEnv* env, jclass, jint sink, jobject rawFrameObj, jlong rawFramePtr,
|
||||
jobject byteBuffer, jint width, jint height, jint pixelFormat,
|
||||
jdouble timeout)
|
||||
{
|
||||
cv::Mat& image = *((cv::Mat*)imageNativeObj);
|
||||
CS_RawFrame* ptr =
|
||||
reinterpret_cast<CS_RawFrame*>(static_cast<intptr_t>(rawFramePtr));
|
||||
auto origDataPtr = ptr->data;
|
||||
ptr->width = width;
|
||||
ptr->height = height;
|
||||
ptr->pixelFormat = pixelFormat;
|
||||
CS_Status status = 0;
|
||||
auto rv = cs::GrabSinkFrameTimeout(sink, image, timeout, &status);
|
||||
CheckStatus(env, status);
|
||||
auto rv = cs::GrabSinkFrameTimeout(static_cast<CS_Sink>(sink), *ptr, timeout,
|
||||
&status);
|
||||
if (!CheckStatus(env, status)) {
|
||||
return 0;
|
||||
}
|
||||
SetRawFrameData(env, rawFrameObj, byteBuffer, origDataPtr != ptr->data, *ptr);
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -1781,4 +1999,32 @@ Java_edu_wpi_cscore_CameraServerJNI_setLogger
|
||||
minLevel);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_cscore_CameraServerJNI
|
||||
* Method: allocateRawFrame
|
||||
* Signature: ()J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_edu_wpi_cscore_CameraServerJNI_allocateRawFrame
|
||||
(JNIEnv*, jclass)
|
||||
{
|
||||
cs::RawFrame* rawFrame = new cs::RawFrame{};
|
||||
intptr_t rawFrameIntPtr = reinterpret_cast<intptr_t>(rawFrame);
|
||||
return static_cast<jlong>(rawFrameIntPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_cscore_CameraServerJNI
|
||||
* Method: freeRawFrame
|
||||
* Signature: (J)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_cscore_CameraServerJNI_freeRawFrame
|
||||
(JNIEnv*, jclass, jlong rawFrame)
|
||||
{
|
||||
cs::RawFrame* ptr =
|
||||
reinterpret_cast<cs::RawFrame*>(static_cast<intptr_t>(rawFrame));
|
||||
delete ptr;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
@@ -20,8 +20,6 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct CvMat;
|
||||
|
||||
/**
|
||||
* @defgroup cscore_c_api cscore C API
|
||||
*
|
||||
@@ -128,7 +126,8 @@ enum CS_SourceKind {
|
||||
CS_SOURCE_UNKNOWN = 0,
|
||||
CS_SOURCE_USB = 1,
|
||||
CS_SOURCE_HTTP = 2,
|
||||
CS_SOURCE_CV = 4
|
||||
CS_SOURCE_CV = 4,
|
||||
CS_SOURCE_RAW = 8,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -144,7 +143,12 @@ enum CS_HttpCameraKind {
|
||||
/**
|
||||
* Sink kinds
|
||||
*/
|
||||
enum CS_SinkKind { CS_SINK_UNKNOWN = 0, CS_SINK_MJPEG = 2, CS_SINK_CV = 4 };
|
||||
enum CS_SinkKind {
|
||||
CS_SINK_UNKNOWN = 0,
|
||||
CS_SINK_MJPEG = 2,
|
||||
CS_SINK_CV = 4,
|
||||
CS_SINK_RAW = 8
|
||||
};
|
||||
|
||||
/**
|
||||
* Listener event kinds
|
||||
@@ -232,6 +236,8 @@ typedef struct CS_UsbCameraInfo {
|
||||
char* name;
|
||||
int otherPathsCount;
|
||||
char** otherPaths;
|
||||
int vendorId;
|
||||
int productId;
|
||||
} CS_UsbCameraInfo;
|
||||
|
||||
/**
|
||||
@@ -351,8 +357,6 @@ char** CS_GetHttpCameraUrls(CS_Source source, int* count, CS_Status* status);
|
||||
* @defgroup cscore_opencv_source_cfunc OpenCV Source Functions
|
||||
* @{
|
||||
*/
|
||||
void CS_PutSourceFrame(CS_Source source, struct CvMat* image,
|
||||
CS_Status* status);
|
||||
void CS_NotifySourceError(CS_Source source, const char* msg, CS_Status* status);
|
||||
void CS_SetSourceConnected(CS_Source source, CS_Bool connected,
|
||||
CS_Status* status);
|
||||
@@ -415,9 +419,6 @@ int CS_GetMjpegServerPort(CS_Sink sink, CS_Status* status);
|
||||
*/
|
||||
void CS_SetSinkDescription(CS_Sink sink, const char* description,
|
||||
CS_Status* status);
|
||||
uint64_t CS_GrabSinkFrame(CS_Sink sink, struct CvMat* image, CS_Status* status);
|
||||
uint64_t CS_GrabSinkFrameTimeout(CS_Sink sink, struct CvMat* image,
|
||||
double timeout, CS_Status* status);
|
||||
char* CS_GetSinkError(CS_Sink sink, CS_Status* status);
|
||||
void CS_SetSinkEnabled(CS_Sink sink, CS_Bool enabled, CS_Status* status);
|
||||
/** @} */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2015-2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2015-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
@@ -21,9 +21,11 @@
|
||||
|
||||
#include "cscore_c.h"
|
||||
|
||||
namespace cv {
|
||||
class Mat;
|
||||
} // namespace cv
|
||||
#ifdef _WIN32
|
||||
// Disable uninitialized variable warnings
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 26495)
|
||||
#endif
|
||||
|
||||
namespace wpi {
|
||||
class json;
|
||||
@@ -54,6 +56,10 @@ struct UsbCameraInfo {
|
||||
std::string name;
|
||||
/** Other path aliases to device (e.g. '/dev/v4l/by-id/...' etc on Linux) */
|
||||
std::vector<std::string> otherPaths;
|
||||
/** USB Vendor Id */
|
||||
int vendorId = -1;
|
||||
/** USB Product Id */
|
||||
int productId = -1;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -286,7 +292,6 @@ std::vector<std::string> GetHttpCameraUrls(CS_Source source, CS_Status* status);
|
||||
* @defgroup cscore_opencv_source_func OpenCV Source Functions
|
||||
* @{
|
||||
*/
|
||||
void PutSourceFrame(CS_Source source, cv::Mat& image, CS_Status* status);
|
||||
void NotifySourceError(CS_Source source, const wpi::Twine& msg,
|
||||
CS_Status* status);
|
||||
void SetSourceConnected(CS_Source source, bool connected, CS_Status* status);
|
||||
@@ -312,6 +317,7 @@ CS_Sink CreateCvSink(const wpi::Twine& name, CS_Status* status);
|
||||
CS_Sink CreateCvSinkCallback(const wpi::Twine& name,
|
||||
std::function<void(uint64_t time)> processFrame,
|
||||
CS_Status* status);
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
@@ -356,9 +362,6 @@ int GetMjpegServerPort(CS_Sink sink, CS_Status* status);
|
||||
*/
|
||||
void SetSinkDescription(CS_Sink sink, const wpi::Twine& description,
|
||||
CS_Status* status);
|
||||
uint64_t GrabSinkFrame(CS_Sink sink, cv::Mat& image, CS_Status* status);
|
||||
uint64_t GrabSinkFrameTimeout(CS_Sink sink, cv::Mat& image, double timeout,
|
||||
CS_Status* status);
|
||||
std::string GetSinkError(CS_Sink sink, CS_Status* status);
|
||||
wpi::StringRef GetSinkError(CS_Sink sink, wpi::SmallVectorImpl<char>& buf,
|
||||
CS_Status* status);
|
||||
@@ -429,18 +432,9 @@ std::vector<std::string> GetNetworkInterfaces();
|
||||
|
||||
} // namespace cs
|
||||
|
||||
/**
|
||||
* @defgroup cscore_cpp_opencv_special cscore C functions taking a cv::Mat*
|
||||
*
|
||||
* These are needed for specific interop implementations.
|
||||
* @{
|
||||
*/
|
||||
extern "C" {
|
||||
uint64_t CS_GrabSinkFrameCpp(CS_Sink sink, cv::Mat* image, CS_Status* status);
|
||||
uint64_t CS_GrabSinkFrameTimeoutCpp(CS_Sink sink, cv::Mat* image,
|
||||
double timeout, CS_Status* status);
|
||||
void CS_PutSourceFrameCpp(CS_Source source, cv::Mat* image, CS_Status* status);
|
||||
} // extern "C"
|
||||
/** @} */
|
||||
#ifdef _WIN32
|
||||
// Disable uninitialized variable warnings
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif // CSCORE_CSCORE_CPP_H_
|
||||
|
||||
209
cscore/src/main/native/include/cscore_cv.h
Normal file
209
cscore/src/main/native/include/cscore_cv.h
Normal file
@@ -0,0 +1,209 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2015-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef CSCORE_CSCORE_CV_H_
|
||||
#define CSCORE_CSCORE_CV_H_
|
||||
|
||||
#include "cscore_c.h"
|
||||
|
||||
#ifdef CSCORE_CSCORE_RAW_CV_H_
|
||||
#error "Cannot include both cscore_cv.h and cscore_raw_cv.h in the same file"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include "cscore_oo.h" // NOLINT(build/include_order)
|
||||
|
||||
#endif
|
||||
|
||||
#if CV_VERSION_MAJOR < 4
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" { // NOLINT(build/include_order)
|
||||
#endif
|
||||
|
||||
struct CvMat;
|
||||
|
||||
void CS_PutSourceFrame(CS_Source source, struct CvMat* image,
|
||||
CS_Status* status);
|
||||
|
||||
uint64_t CS_GrabSinkFrame(CS_Sink sink, struct CvMat* image, CS_Status* status);
|
||||
uint64_t CS_GrabSinkFrameTimeout(CS_Sink sink, struct CvMat* image,
|
||||
double timeout, CS_Status* status);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // CV_VERSION_MAJOR < 4
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include "cscore_oo.h"
|
||||
|
||||
namespace cv {
|
||||
class Mat;
|
||||
} // namespace cv
|
||||
|
||||
namespace cs {
|
||||
|
||||
/**
|
||||
* @defgroup cscore_cpp_opencv_special cscore C functions taking a cv::Mat*
|
||||
*
|
||||
* These are needed for specific interop implementations.
|
||||
* @{
|
||||
*/
|
||||
extern "C" {
|
||||
uint64_t CS_GrabSinkFrameCpp(CS_Sink sink, cv::Mat* image, CS_Status* status);
|
||||
uint64_t CS_GrabSinkFrameTimeoutCpp(CS_Sink sink, cv::Mat* image,
|
||||
double timeout, CS_Status* status);
|
||||
void CS_PutSourceFrameCpp(CS_Source source, cv::Mat* image, CS_Status* status);
|
||||
} // extern "C"
|
||||
/** @} */
|
||||
|
||||
void PutSourceFrame(CS_Source source, cv::Mat& image, CS_Status* status);
|
||||
uint64_t GrabSinkFrame(CS_Sink sink, cv::Mat& image, CS_Status* status);
|
||||
uint64_t GrabSinkFrameTimeout(CS_Sink sink, cv::Mat& image, double timeout,
|
||||
CS_Status* status);
|
||||
|
||||
/**
|
||||
* A source for user code to provide OpenCV images as video frames.
|
||||
* These sources require the WPILib OpenCV builds.
|
||||
* For an alternate OpenCV, include "cscore_raw_cv.h" instead, and
|
||||
* include your Mat header before that header.
|
||||
*/
|
||||
class CvSource : public ImageSource {
|
||||
public:
|
||||
CvSource() = default;
|
||||
|
||||
/**
|
||||
* Create an OpenCV source.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
* @param mode Video mode being generated
|
||||
*/
|
||||
CvSource(const wpi::Twine& name, const VideoMode& mode);
|
||||
|
||||
/**
|
||||
* Create an OpenCV source.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
* @param pixelFormat Pixel format
|
||||
* @param width width
|
||||
* @param height height
|
||||
* @param fps fps
|
||||
*/
|
||||
CvSource(const wpi::Twine& name, VideoMode::PixelFormat pixelFormat,
|
||||
int width, int height, int fps);
|
||||
|
||||
/**
|
||||
* Put an OpenCV image and notify sinks.
|
||||
*
|
||||
* <p>Only 8-bit single-channel or 3-channel (with BGR channel order) images
|
||||
* are supported. If the format, depth or channel order is different, use
|
||||
* cv::Mat::convertTo() and/or cv::cvtColor() to convert it first.
|
||||
*
|
||||
* @param image OpenCV image
|
||||
*/
|
||||
void PutFrame(cv::Mat& image);
|
||||
};
|
||||
|
||||
/**
|
||||
* A sink for user code to accept video frames as OpenCV images.
|
||||
* These sinks require the WPILib OpenCV builds.
|
||||
* For an alternate OpenCV, include "cscore_raw_cv.h" instead, and
|
||||
* include your Mat header before that header.
|
||||
*/
|
||||
class CvSink : public ImageSink {
|
||||
public:
|
||||
CvSink() = default;
|
||||
|
||||
/**
|
||||
* Create a sink for accepting OpenCV images.
|
||||
*
|
||||
* <p>WaitForFrame() must be called on the created sink to get each new
|
||||
* image.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
*/
|
||||
explicit CvSink(const wpi::Twine& name);
|
||||
|
||||
/**
|
||||
* Create a sink for accepting OpenCV images in a separate thread.
|
||||
*
|
||||
* <p>A thread will be created that calls WaitForFrame() and calls the
|
||||
* processFrame() callback each time a new frame arrives.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
* @param processFrame Frame processing function; will be called with a
|
||||
* time=0 if an error occurred. processFrame should call GetImage()
|
||||
* or GetError() as needed, but should not call (except in very
|
||||
* unusual circumstances) WaitForImage().
|
||||
*/
|
||||
CvSink(const wpi::Twine& name,
|
||||
std::function<void(uint64_t time)> processFrame);
|
||||
|
||||
/**
|
||||
* Wait for the next frame and get the image.
|
||||
* Times out (returning 0) after timeout seconds.
|
||||
* The provided image will have three 8-bit channels stored in BGR order.
|
||||
*
|
||||
* @return Frame time, or 0 on error (call GetError() to obtain the error
|
||||
* message); the frame time is in the same time base as wpi::Now(),
|
||||
* and is in 1 us increments.
|
||||
*/
|
||||
uint64_t GrabFrame(cv::Mat& image, double timeout = 0.225) const;
|
||||
|
||||
/**
|
||||
* Wait for the next frame and get the image. May block forever.
|
||||
* The provided image will have three 8-bit channels stored in BGR order.
|
||||
*
|
||||
* @return Frame time, or 0 on error (call GetError() to obtain the error
|
||||
* message); the frame time is in the same time base as wpi::Now(),
|
||||
* and is in 1 us increments.
|
||||
*/
|
||||
uint64_t GrabFrameNoTimeout(cv::Mat& image) const;
|
||||
};
|
||||
|
||||
inline CvSource::CvSource(const wpi::Twine& name, const VideoMode& mode) {
|
||||
m_handle = CreateCvSource(name, mode, &m_status);
|
||||
}
|
||||
|
||||
inline CvSource::CvSource(const wpi::Twine& name, VideoMode::PixelFormat format,
|
||||
int width, int height, int fps) {
|
||||
m_handle =
|
||||
CreateCvSource(name, VideoMode{format, width, height, fps}, &m_status);
|
||||
}
|
||||
|
||||
inline void CvSource::PutFrame(cv::Mat& image) {
|
||||
m_status = 0;
|
||||
PutSourceFrame(m_handle, image, &m_status);
|
||||
}
|
||||
|
||||
inline CvSink::CvSink(const wpi::Twine& name) {
|
||||
m_handle = CreateCvSink(name, &m_status);
|
||||
}
|
||||
|
||||
inline CvSink::CvSink(const wpi::Twine& name,
|
||||
std::function<void(uint64_t time)> processFrame) {
|
||||
m_handle = CreateCvSinkCallback(name, processFrame, &m_status);
|
||||
}
|
||||
|
||||
inline uint64_t CvSink::GrabFrame(cv::Mat& image, double timeout) const {
|
||||
m_status = 0;
|
||||
return GrabSinkFrameTimeout(m_handle, image, timeout, &m_status);
|
||||
}
|
||||
|
||||
inline uint64_t CvSink::GrabFrameNoTimeout(cv::Mat& image) const {
|
||||
m_status = 0;
|
||||
return GrabSinkFrame(m_handle, image, &m_status);
|
||||
}
|
||||
|
||||
} // namespace cs
|
||||
|
||||
#endif
|
||||
|
||||
#endif // CSCORE_CSCORE_CV_H_
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2015-2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2015-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
@@ -28,7 +28,7 @@ namespace cs {
|
||||
*/
|
||||
|
||||
// Forward declarations so friend declarations work correctly
|
||||
class CvSource;
|
||||
class ImageSource;
|
||||
class VideoEvent;
|
||||
class VideoSink;
|
||||
class VideoSource;
|
||||
@@ -37,7 +37,7 @@ class VideoSource;
|
||||
* A source or sink property.
|
||||
*/
|
||||
class VideoProperty {
|
||||
friend class CvSource;
|
||||
friend class ImageSource;
|
||||
friend class VideoEvent;
|
||||
friend class VideoSink;
|
||||
friend class VideoSource;
|
||||
@@ -51,7 +51,7 @@ class VideoProperty {
|
||||
kEnum = CS_PROP_ENUM
|
||||
};
|
||||
|
||||
VideoProperty() : m_handle(0), m_kind(kNone) {}
|
||||
VideoProperty() : m_status(0), m_handle(0), m_kind(kNone) {}
|
||||
|
||||
std::string GetName() const;
|
||||
|
||||
@@ -617,43 +617,13 @@ class AxisCamera : public HttpCamera {
|
||||
};
|
||||
|
||||
/**
|
||||
* A source for user code to provide OpenCV images as video frames.
|
||||
* A base class for single image providing sources.
|
||||
*/
|
||||
class CvSource : public VideoSource {
|
||||
class ImageSource : public VideoSource {
|
||||
protected:
|
||||
ImageSource() = default;
|
||||
|
||||
public:
|
||||
CvSource() = default;
|
||||
|
||||
/**
|
||||
* Create an OpenCV source.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
* @param mode Video mode being generated
|
||||
*/
|
||||
CvSource(const wpi::Twine& name, const VideoMode& mode);
|
||||
|
||||
/**
|
||||
* Create an OpenCV source.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
* @param pixelFormat Pixel format
|
||||
* @param width width
|
||||
* @param height height
|
||||
* @param fps fps
|
||||
*/
|
||||
CvSource(const wpi::Twine& name, VideoMode::PixelFormat pixelFormat,
|
||||
int width, int height, int fps);
|
||||
|
||||
/**
|
||||
* Put an OpenCV image and notify sinks.
|
||||
*
|
||||
* <p>Only 8-bit single-channel or 3-channel (with BGR channel order) images
|
||||
* are supported. If the format, depth or channel order is different, use
|
||||
* cv::Mat::convertTo() and/or cv::cvtColor() to convert it first.
|
||||
*
|
||||
* @param image OpenCV image
|
||||
*/
|
||||
void PutFrame(cv::Mat& image);
|
||||
|
||||
/**
|
||||
* Signal sinks that an error has occurred. This should be called instead
|
||||
* of NotifyFrame when an error occurs.
|
||||
@@ -979,37 +949,13 @@ class MjpegServer : public VideoSink {
|
||||
};
|
||||
|
||||
/**
|
||||
* A sink for user code to accept video frames as OpenCV images.
|
||||
* A base class for single image reading sinks.
|
||||
*/
|
||||
class CvSink : public VideoSink {
|
||||
class ImageSink : public VideoSink {
|
||||
protected:
|
||||
ImageSink() = default;
|
||||
|
||||
public:
|
||||
CvSink() = default;
|
||||
|
||||
/**
|
||||
* Create a sink for accepting OpenCV images.
|
||||
*
|
||||
* <p>WaitForFrame() must be called on the created sink to get each new
|
||||
* image.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
*/
|
||||
explicit CvSink(const wpi::Twine& name);
|
||||
|
||||
/**
|
||||
* Create a sink for accepting OpenCV images in a separate thread.
|
||||
*
|
||||
* <p>A thread will be created that calls WaitForFrame() and calls the
|
||||
* processFrame() callback each time a new frame arrives.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
* @param processFrame Frame processing function; will be called with a
|
||||
* time=0 if an error occurred. processFrame should call GetImage()
|
||||
* or GetError() as needed, but should not call (except in very
|
||||
* unusual circumstances) WaitForImage().
|
||||
*/
|
||||
CvSink(const wpi::Twine& name,
|
||||
std::function<void(uint64_t time)> processFrame);
|
||||
|
||||
/**
|
||||
* Set sink description.
|
||||
*
|
||||
@@ -1017,27 +963,6 @@ class CvSink : public VideoSink {
|
||||
*/
|
||||
void SetDescription(const wpi::Twine& description);
|
||||
|
||||
/**
|
||||
* Wait for the next frame and get the image.
|
||||
* Times out (returning 0) after timeout seconds.
|
||||
* The provided image will have three 8-bit channels stored in BGR order.
|
||||
*
|
||||
* @return Frame time, or 0 on error (call GetError() to obtain the error
|
||||
* message); the frame time is in the same time base as wpi::Now(),
|
||||
* and is in 1 us increments.
|
||||
*/
|
||||
uint64_t GrabFrame(cv::Mat& image, double timeout = 0.225) const;
|
||||
|
||||
/**
|
||||
* Wait for the next frame and get the image. May block forever.
|
||||
* The provided image will have three 8-bit channels stored in BGR order.
|
||||
*
|
||||
* @return Frame time, or 0 on error (call GetError() to obtain the error
|
||||
* message); the frame time is in the same time base as wpi::Now(),
|
||||
* and is in 1 us increments.
|
||||
*/
|
||||
uint64_t GrabFrameNoTimeout(cv::Mat& image) const;
|
||||
|
||||
/**
|
||||
* Get error string. Call this if WaitForFrame() returns 0 to determine
|
||||
* what the error is.
|
||||
|
||||
@@ -76,7 +76,7 @@ inline VideoProperty::VideoProperty(CS_Property handle) : m_handle(handle) {
|
||||
}
|
||||
|
||||
inline VideoProperty::VideoProperty(CS_Property handle, Kind kind)
|
||||
: m_handle(handle), m_kind(kind) {}
|
||||
: m_status(0), m_handle(handle), m_kind(kind) {}
|
||||
|
||||
inline VideoSource::VideoSource(const VideoSource& source)
|
||||
: m_handle(source.m_handle == 0 ? 0
|
||||
@@ -378,37 +378,22 @@ inline AxisCamera::AxisCamera(const wpi::Twine& name,
|
||||
std::initializer_list<T> hosts)
|
||||
: HttpCamera(name, HostToUrl(hosts), kAxis) {}
|
||||
|
||||
inline CvSource::CvSource(const wpi::Twine& name, const VideoMode& mode) {
|
||||
m_handle = CreateCvSource(name, mode, &m_status);
|
||||
}
|
||||
|
||||
inline CvSource::CvSource(const wpi::Twine& name, VideoMode::PixelFormat format,
|
||||
int width, int height, int fps) {
|
||||
m_handle =
|
||||
CreateCvSource(name, VideoMode{format, width, height, fps}, &m_status);
|
||||
}
|
||||
|
||||
inline void CvSource::PutFrame(cv::Mat& image) {
|
||||
m_status = 0;
|
||||
PutSourceFrame(m_handle, image, &m_status);
|
||||
}
|
||||
|
||||
inline void CvSource::NotifyError(const wpi::Twine& msg) {
|
||||
inline void ImageSource::NotifyError(const wpi::Twine& msg) {
|
||||
m_status = 0;
|
||||
NotifySourceError(m_handle, msg, &m_status);
|
||||
}
|
||||
|
||||
inline void CvSource::SetConnected(bool connected) {
|
||||
inline void ImageSource::SetConnected(bool connected) {
|
||||
m_status = 0;
|
||||
SetSourceConnected(m_handle, connected, &m_status);
|
||||
}
|
||||
|
||||
inline void CvSource::SetDescription(const wpi::Twine& description) {
|
||||
inline void ImageSource::SetDescription(const wpi::Twine& description) {
|
||||
m_status = 0;
|
||||
SetSourceDescription(m_handle, description, &m_status);
|
||||
}
|
||||
|
||||
inline VideoProperty CvSource::CreateProperty(const wpi::Twine& name,
|
||||
inline VideoProperty ImageSource::CreateProperty(const wpi::Twine& name,
|
||||
VideoProperty::Kind kind,
|
||||
int minimum, int maximum,
|
||||
int step, int defaultValue,
|
||||
@@ -419,7 +404,7 @@ inline VideoProperty CvSource::CreateProperty(const wpi::Twine& name,
|
||||
minimum, maximum, step, defaultValue, value, &m_status)};
|
||||
}
|
||||
|
||||
inline VideoProperty CvSource::CreateIntegerProperty(const wpi::Twine& name,
|
||||
inline VideoProperty ImageSource::CreateIntegerProperty(const wpi::Twine& name,
|
||||
int minimum, int maximum,
|
||||
int step, int defaultValue,
|
||||
int value) {
|
||||
@@ -429,7 +414,7 @@ inline VideoProperty CvSource::CreateIntegerProperty(const wpi::Twine& name,
|
||||
minimum, maximum, step, defaultValue, value, &m_status)};
|
||||
}
|
||||
|
||||
inline VideoProperty CvSource::CreateBooleanProperty(const wpi::Twine& name,
|
||||
inline VideoProperty ImageSource::CreateBooleanProperty(const wpi::Twine& name,
|
||||
bool defaultValue,
|
||||
bool value) {
|
||||
m_status = 0;
|
||||
@@ -438,7 +423,7 @@ inline VideoProperty CvSource::CreateBooleanProperty(const wpi::Twine& name,
|
||||
0, 1, 1, defaultValue ? 1 : 0, value ? 1 : 0, &m_status)};
|
||||
}
|
||||
|
||||
inline VideoProperty CvSource::CreateStringProperty(const wpi::Twine& name,
|
||||
inline VideoProperty ImageSource::CreateStringProperty(const wpi::Twine& name,
|
||||
const wpi::Twine& value) {
|
||||
m_status = 0;
|
||||
auto prop = VideoProperty{CreateSourceProperty(
|
||||
@@ -449,14 +434,14 @@ inline VideoProperty CvSource::CreateStringProperty(const wpi::Twine& name,
|
||||
}
|
||||
|
||||
|
||||
inline void CvSource::SetEnumPropertyChoices(
|
||||
inline void ImageSource::SetEnumPropertyChoices(
|
||||
const VideoProperty& property, wpi::ArrayRef<std::string> choices) {
|
||||
m_status = 0;
|
||||
SetSourceEnumPropertyChoices(m_handle, property.m_handle, choices, &m_status);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void CvSource::SetEnumPropertyChoices(const VideoProperty& property,
|
||||
inline void ImageSource::SetEnumPropertyChoices(const VideoProperty& property,
|
||||
std::initializer_list<T> choices) {
|
||||
std::vector<std::string> vec;
|
||||
vec.reserve(choices.size());
|
||||
@@ -575,36 +560,17 @@ inline void MjpegServer::SetDefaultCompression(int quality) {
|
||||
quality, &m_status);
|
||||
}
|
||||
|
||||
inline CvSink::CvSink(const wpi::Twine& name) {
|
||||
m_handle = CreateCvSink(name, &m_status);
|
||||
}
|
||||
|
||||
inline CvSink::CvSink(const wpi::Twine& name,
|
||||
std::function<void(uint64_t time)> processFrame) {
|
||||
m_handle = CreateCvSinkCallback(name, processFrame, &m_status);
|
||||
}
|
||||
|
||||
inline void CvSink::SetDescription(const wpi::Twine& description) {
|
||||
inline void ImageSink::SetDescription(const wpi::Twine& description) {
|
||||
m_status = 0;
|
||||
SetSinkDescription(m_handle, description, &m_status);
|
||||
}
|
||||
|
||||
inline uint64_t CvSink::GrabFrame(cv::Mat& image, double timeout) const {
|
||||
m_status = 0;
|
||||
return GrabSinkFrameTimeout(m_handle, image, timeout, &m_status);
|
||||
}
|
||||
|
||||
inline uint64_t CvSink::GrabFrameNoTimeout(cv::Mat& image) const {
|
||||
m_status = 0;
|
||||
return GrabSinkFrame(m_handle, image, &m_status);
|
||||
}
|
||||
|
||||
inline std::string CvSink::GetError() const {
|
||||
inline std::string ImageSink::GetError() const {
|
||||
m_status = 0;
|
||||
return GetSinkError(m_handle, &m_status);
|
||||
}
|
||||
|
||||
inline void CvSink::SetEnabled(bool enabled) {
|
||||
inline void ImageSink::SetEnabled(bool enabled) {
|
||||
m_status = 0;
|
||||
SetSinkEnabled(m_handle, enabled, &m_status);
|
||||
}
|
||||
|
||||
234
cscore/src/main/native/include/cscore_raw.h
Normal file
234
cscore/src/main/native/include/cscore_raw.h
Normal file
@@ -0,0 +1,234 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef CSCORE_CSCORE_RAW_H_
|
||||
#define CSCORE_CSCORE_RAW_H_
|
||||
|
||||
#include "cscore_c.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include "cscore_oo.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Raw Frame
|
||||
*/
|
||||
typedef struct CS_RawFrame {
|
||||
char* data;
|
||||
int dataLength;
|
||||
int pixelFormat;
|
||||
int width;
|
||||
int height;
|
||||
int totalData;
|
||||
} CS_RawFrame;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup cscore_raw_cfunc Raw Image Functions
|
||||
* @{
|
||||
*/
|
||||
void CS_AllocateRawFrameData(CS_RawFrame* frame, int requestedSize);
|
||||
void CS_FreeRawFrameData(CS_RawFrame* frame);
|
||||
|
||||
uint64_t CS_GrabRawSinkFrame(CS_Sink sink, struct CS_RawFrame* rawImage,
|
||||
CS_Status* status);
|
||||
uint64_t CS_GrabRawSinkFrameTimeout(CS_Sink sink, struct CS_RawFrame* rawImage,
|
||||
double timeout, CS_Status* status);
|
||||
|
||||
CS_Sink CS_CreateRawSink(const char* name, CS_Status* status);
|
||||
|
||||
CS_Sink CS_CreateRawSinkCallback(const char* name, void* data,
|
||||
void (*processFrame)(void* data,
|
||||
uint64_t time),
|
||||
CS_Status* status);
|
||||
|
||||
void CS_PutRawSourceFrame(CS_Source source, const struct CS_RawFrame* image,
|
||||
CS_Status* status);
|
||||
|
||||
CS_Source CS_CreateRawSource(const char* name, const CS_VideoMode* mode,
|
||||
CS_Status* status);
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace cs {
|
||||
|
||||
struct RawFrame : public CS_RawFrame {
|
||||
RawFrame() {
|
||||
data = nullptr;
|
||||
dataLength = 0;
|
||||
pixelFormat = CS_PIXFMT_UNKNOWN;
|
||||
width = 0;
|
||||
height = 0;
|
||||
totalData = 0;
|
||||
}
|
||||
|
||||
~RawFrame() { CS_FreeRawFrameData(this); }
|
||||
};
|
||||
|
||||
/**
|
||||
* @defgroup cscore_raw_func Raw Image Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
CS_Source CreateRawSource(const wpi::Twine& name, const VideoMode& mode,
|
||||
CS_Status* status);
|
||||
|
||||
CS_Sink CreateRawSink(const wpi::Twine& name, CS_Status* status);
|
||||
CS_Sink CreateRawSinkCallback(const wpi::Twine& name,
|
||||
std::function<void(uint64_t time)> processFrame,
|
||||
CS_Status* status);
|
||||
|
||||
void PutSourceFrame(CS_Source source, const CS_RawFrame& image,
|
||||
CS_Status* status);
|
||||
uint64_t GrabSinkFrame(CS_Sink sink, CS_RawFrame& image, CS_Status* status);
|
||||
uint64_t GrabSinkFrameTimeout(CS_Sink sink, CS_RawFrame& image, double timeout,
|
||||
CS_Status* status);
|
||||
|
||||
/**
|
||||
* A source for user code to provide video frames as raw bytes.
|
||||
*
|
||||
* This is a complex API, most cases should use CvSource.
|
||||
*/
|
||||
class RawSource : public ImageSource {
|
||||
public:
|
||||
RawSource() = default;
|
||||
|
||||
/**
|
||||
* Create a raw frame source.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
* @param mode Video mode being generated
|
||||
*/
|
||||
RawSource(const wpi::Twine& name, const VideoMode& mode);
|
||||
|
||||
/**
|
||||
* Create a raw frame source.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
* @param pixelFormat Pixel format
|
||||
* @param width width
|
||||
* @param height height
|
||||
* @param fps fps
|
||||
*/
|
||||
RawSource(const wpi::Twine& name, VideoMode::PixelFormat pixelFormat,
|
||||
int width, int height, int fps);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Put a raw image and notify sinks.
|
||||
*
|
||||
* @param image raw frame image
|
||||
*/
|
||||
void PutFrame(RawFrame& image);
|
||||
};
|
||||
|
||||
/**
|
||||
* A sink for user code to accept video frames as raw bytes.
|
||||
*
|
||||
* This is a complex API, most cases should use CvSource.
|
||||
*/
|
||||
class RawSink : public ImageSink {
|
||||
public:
|
||||
RawSink() = default;
|
||||
|
||||
/**
|
||||
* Create a sink for accepting raw images.
|
||||
*
|
||||
* <p>GrabFrame() must be called on the created sink to get each new
|
||||
* image.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
*/
|
||||
explicit RawSink(const wpi::Twine& name);
|
||||
|
||||
/**
|
||||
* Create a sink for accepting raws images in a separate thread.
|
||||
*
|
||||
* <p>A thread will be created that calls WaitForFrame() and calls the
|
||||
* processFrame() callback each time a new frame arrives.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
* @param processFrame Frame processing function; will be called with a
|
||||
* time=0 if an error occurred. processFrame should call GetImage()
|
||||
* or GetError() as needed, but should not call (except in very
|
||||
* unusual circumstances) WaitForImage().
|
||||
*/
|
||||
RawSink(const wpi::Twine& name,
|
||||
std::function<void(uint64_t time)> processFrame);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Wait for the next frame and get the image.
|
||||
* Times out (returning 0) after timeout seconds.
|
||||
* The provided image will have three 8-bit channels stored in BGR order.
|
||||
*
|
||||
* @return Frame time, or 0 on error (call GetError() to obtain the error
|
||||
* message); the frame time is in the same time base as wpi::Now(),
|
||||
* and is in 1 us increments.
|
||||
*/
|
||||
uint64_t GrabFrame(RawFrame& image, double timeout = 0.225) const;
|
||||
|
||||
/**
|
||||
* Wait for the next frame and get the image. May block forever.
|
||||
* The provided image will have three 8-bit channels stored in BGR order.
|
||||
*
|
||||
* @return Frame time, or 0 on error (call GetError() to obtain the error
|
||||
* message); the frame time is in the same time base as wpi::Now(),
|
||||
* and is in 1 us increments.
|
||||
*/
|
||||
uint64_t GrabFrameNoTimeout(RawFrame& image) const;
|
||||
};
|
||||
|
||||
inline RawSource::RawSource(const wpi::Twine& name, const VideoMode& mode) {
|
||||
m_handle = CreateRawSource(name, mode, &m_status);
|
||||
}
|
||||
|
||||
inline RawSource::RawSource(const wpi::Twine& name,
|
||||
VideoMode::PixelFormat format, int width,
|
||||
int height, int fps) {
|
||||
m_handle =
|
||||
CreateRawSource(name, VideoMode{format, width, height, fps}, &m_status);
|
||||
}
|
||||
|
||||
inline void RawSource::PutFrame(RawFrame& image) {
|
||||
m_status = 0;
|
||||
PutSourceFrame(m_handle, image, &m_status);
|
||||
}
|
||||
|
||||
inline RawSink::RawSink(const wpi::Twine& name) {
|
||||
m_handle = CreateRawSink(name, &m_status);
|
||||
}
|
||||
|
||||
inline RawSink::RawSink(const wpi::Twine& name,
|
||||
std::function<void(uint64_t time)> processFrame) {
|
||||
m_handle = CreateRawSinkCallback(name, processFrame, &m_status);
|
||||
}
|
||||
|
||||
inline uint64_t RawSink::GrabFrame(RawFrame& image, double timeout) const {
|
||||
m_status = 0;
|
||||
return GrabSinkFrameTimeout(m_handle, image, timeout, &m_status);
|
||||
}
|
||||
|
||||
inline uint64_t RawSink::GrabFrameNoTimeout(RawFrame& image) const {
|
||||
m_status = 0;
|
||||
return GrabSinkFrame(m_handle, image, &m_status);
|
||||
}
|
||||
|
||||
} // namespace cs
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif
|
||||
|
||||
#endif // CSCORE_CSCORE_RAW_H_
|
||||
218
cscore/src/main/native/include/cscore_raw_cv.h
Normal file
218
cscore/src/main/native/include/cscore_raw_cv.h
Normal file
@@ -0,0 +1,218 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2015-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef CSCORE_CSCORE_RAW_CV_H_
|
||||
#define CSCORE_CSCORE_RAW_CV_H_
|
||||
|
||||
#ifdef CSCORE_CSCORE_CV_H_
|
||||
#error "Cannot include both cscore_cv.h and cscore_raw_cv.h in the same file"
|
||||
#endif
|
||||
|
||||
#include "cscore_raw.h"
|
||||
|
||||
namespace cs {
|
||||
/**
|
||||
* A source for using the raw frame API to provide opencv images.
|
||||
*
|
||||
* If you are using the WPILib OpenCV builds, do not use this, and
|
||||
* instead include "cscore_cv.h" to get a more performant version.
|
||||
*
|
||||
* This is not dependent on any opencv binary ABI, and can be used
|
||||
* with versions of OpenCV that are not 3. If using OpenCV 3, use
|
||||
* CvSource.
|
||||
*/
|
||||
class RawCvSource : public RawSource {
|
||||
public:
|
||||
RawCvSource() = default;
|
||||
|
||||
/**
|
||||
* Create a Raw OpenCV source.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
* @param mode Video mode being generated
|
||||
*/
|
||||
RawCvSource(const wpi::Twine& name, const VideoMode& mode);
|
||||
|
||||
/**
|
||||
* Create a Raw OpenCV source.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
* @param pixelFormat Pixel format
|
||||
* @param width width
|
||||
* @param height height
|
||||
* @param fps fps
|
||||
*/
|
||||
RawCvSource(const wpi::Twine& name, VideoMode::PixelFormat pixelFormat,
|
||||
int width, int height, int fps);
|
||||
|
||||
/**
|
||||
* Put an OpenCV image and notify sinks.
|
||||
*
|
||||
* <p>Only 8-bit single-channel or 3-channel (with BGR channel order) images
|
||||
* are supported. If the format, depth or channel order is different, use
|
||||
* cv::Mat::convertTo() and/or cv::cvtColor() to convert it first.
|
||||
*
|
||||
* @param image OpenCV image
|
||||
*/
|
||||
void PutFrame(cv::Mat& image);
|
||||
|
||||
private:
|
||||
RawFrame rawFrame;
|
||||
};
|
||||
|
||||
/**
|
||||
* A sink for user code to accept raw video frames as OpenCV images.
|
||||
*
|
||||
* If you are using the WPILib OpenCV builds, do not use this, and
|
||||
* instead include "cscore_cv.h" to get a more performant version.
|
||||
*
|
||||
* This is not dependent on any opencv binary ABI, and can be used
|
||||
* with versions of OpenCV that are not 3. If using OpenCV 3, use
|
||||
* CvSink.
|
||||
*/
|
||||
class RawCvSink : public RawSink {
|
||||
public:
|
||||
RawCvSink() = default;
|
||||
|
||||
/**
|
||||
* Create a sink for accepting OpenCV images.
|
||||
*
|
||||
* <p>WaitForFrame() must be called on the created sink to get each new
|
||||
* image.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
*/
|
||||
explicit RawCvSink(const wpi::Twine& name);
|
||||
|
||||
/**
|
||||
* Create a sink for accepting OpenCV images in a separate thread.
|
||||
*
|
||||
* <p>A thread will be created that calls WaitForFrame() and calls the
|
||||
* processFrame() callback each time a new frame arrives.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
* @param processFrame Frame processing function; will be called with a
|
||||
* time=0 if an error occurred. processFrame should call GetImage()
|
||||
* or GetError() as needed, but should not call (except in very
|
||||
* unusual circumstances) WaitForImage().
|
||||
*/
|
||||
RawCvSink(const wpi::Twine& name,
|
||||
std::function<void(uint64_t time)> processFrame);
|
||||
|
||||
/**
|
||||
* Wait for the next frame and get the image.
|
||||
* Times out (returning 0) after timeout seconds.
|
||||
* The provided image will have three 8-bit channels stored in BGR order.
|
||||
*
|
||||
* @return Frame time, or 0 on error (call GetError() to obtain the error
|
||||
* message); the frame time is in the same time base as wpi::Now(),
|
||||
* and is in 1 us increments.
|
||||
*/
|
||||
uint64_t GrabFrame(cv::Mat& image, double timeout = 0.225);
|
||||
|
||||
/**
|
||||
* Wait for the next frame and get the image. May block forever.
|
||||
* The provided image will have three 8-bit channels stored in BGR order.
|
||||
*
|
||||
* @return Frame time, or 0 on error (call GetError() to obtain the error
|
||||
* message); the frame time is in the same time base as wpi::Now(),
|
||||
* and is in 1 us increments.
|
||||
*/
|
||||
uint64_t GrabFrameNoTimeout(cv::Mat& image);
|
||||
|
||||
/**
|
||||
* Wait for the next frame and get the image.
|
||||
* Times out (returning 0) after timeout seconds.
|
||||
* The provided image will have three 8-bit channels stored in BGR order.
|
||||
*
|
||||
* @return Frame time, or 0 on error (call GetError() to obtain the error
|
||||
* message); the frame time is in the same time base as wpi::Now(),
|
||||
* and is in 1 us increments.
|
||||
*/
|
||||
uint64_t GrabFrameDirect(cv::Mat& image, double timeout = 0.225);
|
||||
|
||||
/**
|
||||
* Wait for the next frame and get the image. May block forever.
|
||||
* The provided image will have three 8-bit channels stored in BGR order.
|
||||
*
|
||||
* @return Frame time, or 0 on error (call GetError() to obtain the error
|
||||
* message); the frame time is in the same time base as wpi::Now(),
|
||||
* and is in 1 us increments.
|
||||
*/
|
||||
uint64_t GrabFrameNoTimeoutDirect(cv::Mat& image);
|
||||
|
||||
private:
|
||||
RawFrame rawFrame;
|
||||
};
|
||||
|
||||
inline RawCvSource::RawCvSource(const wpi::Twine& name, const VideoMode& mode)
|
||||
: RawSource{name, mode} {}
|
||||
|
||||
inline RawCvSource::RawCvSource(const wpi::Twine& name,
|
||||
VideoMode::PixelFormat format, int width,
|
||||
int height, int fps)
|
||||
: RawSource{name, format, width, height, fps} {}
|
||||
|
||||
inline void RawCvSource::PutFrame(cv::Mat& image) {
|
||||
m_status = 0;
|
||||
rawFrame.data = reinterpret_cast<char*>(image.data);
|
||||
rawFrame.width = image.cols;
|
||||
rawFrame.height = image.rows;
|
||||
rawFrame.totalData = image.total() * image.channels;
|
||||
rawFrame.pixelFormat = image.channels == 3 ? CS_PIXFMT_BGR : CS_PIXFMT_GRAY;
|
||||
PutSourceFrame(m_handle, rawFrame, &m_status);
|
||||
}
|
||||
|
||||
inline RawCvSink::RawCvSink(const wpi::Twine& name) : RawSink{name} {}
|
||||
|
||||
inline RawCvSink::RawCvSink(const wpi::Twine& name,
|
||||
std::function<void(uint64_t time)> processFrame)
|
||||
: RawSink{name, processFrame} {}
|
||||
|
||||
inline uint64_t RawCvSink::GrabFrame(cv::Mat& image, double timeout) {
|
||||
cv::Mat tmpMat;
|
||||
auto retVal = GrabFrameDirect(tmpMat);
|
||||
if (retVal <= 0) {
|
||||
return retVal;
|
||||
}
|
||||
tmpMat.copyTo(image);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
inline uint64_t RawCvSink::GrabFrameNoTimeout(cv::Mat& image) {
|
||||
cv::Mat tmpMat;
|
||||
auto retVal = GrabFrameNoTimeoutDirect(tmpMat);
|
||||
if (retVal <= 0) {
|
||||
return retVal;
|
||||
}
|
||||
tmpMat.copyTo(image);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
inline uint64_t RawCvSink::GrabFrameDirect(cv::Mat& image, double timeout) {
|
||||
rawFrame.height = 0;
|
||||
rawFrame.width = 0;
|
||||
rawFrame.pixelFormat = CS_PixelFormat::CS_PIXFMT_BGR;
|
||||
m_status = RawSink::GrabFrame(rawFrame, timeout);
|
||||
if (m_status <= 0) return m_status;
|
||||
image = cv::Mat{rawFrame.height, rawFrame.width, CV_8UC3, rawFrame.data};
|
||||
return m_status;
|
||||
}
|
||||
|
||||
inline uint64_t RawCvSink::GrabFrameNoTimeoutDirect(cv::Mat& image) {
|
||||
rawFrame.height = 0;
|
||||
rawFrame.width = 0;
|
||||
rawFrame.pixelFormat = CS_PixelFormat::CS_PIXFMT_BGR;
|
||||
m_status = RawSink::GrabFrameNoTimeout(rawFrame);
|
||||
if (m_status <= 0) return m_status;
|
||||
image = cv::Mat{rawFrame.height, rawFrame.width, CV_8UC3, rawFrame.data};
|
||||
return m_status;
|
||||
}
|
||||
|
||||
} // namespace cs
|
||||
|
||||
#endif // CSCORE_CSCORE_RAW_CV_H_
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2015-2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2015-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
@@ -132,8 +132,9 @@ void NetworkListener::Impl::Thread::Main() {
|
||||
break; // XXX: is this the right thing to do here?
|
||||
}
|
||||
if (len == 0) continue; // EOF?
|
||||
unsigned int ulen = static_cast<unsigned int>(len);
|
||||
for (struct nlmsghdr* nh = reinterpret_cast<struct nlmsghdr*>(buf);
|
||||
NLMSG_OK(nh, len); nh = NLMSG_NEXT(nh, len)) {
|
||||
NLMSG_OK(nh, ulen); nh = NLMSG_NEXT(nh, ulen)) {
|
||||
if (nh->nlmsg_type == NLMSG_DONE) break;
|
||||
if (nh->nlmsg_type == RTM_NEWLINK || nh->nlmsg_type == RTM_DELLINK ||
|
||||
nh->nlmsg_type == RTM_NEWADDR || nh->nlmsg_type == RTM_DELADDR) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user