Squashed 'third_party/allwpilib/' changes from 66b57f032..e473a00f9
e473a00f9 [wpiutil] Base64: Add unsigned span/vector variants (#3702)
52f2d580e [wpiutil] raw_uv_ostream: Add reset() (#3701)
d7b1e3576 [wpiutil] WebSocket: move std::function (#3700)
93799fbe9 [examples] Fix description of TrapezoidProfileSubsystem (#3699)
b84644740 [wpimath] Document pose estimator states, inputs, and outputs (#3698)
2dc35c139 [wpimath] Fix classpaths for JNI class loads (#3697)
2cb171f6f [docs] Set Doxygen extract_all to true and fix Doxygen failures (#3695)
a939cd9c8 [wpimath] Print uncontrollable/unobservable models in LQR and KF (#3694)
d5270d113 [wpimath] Clean up C++ StateSpaceUtil tests (#3692)
b20903960 [wpimath] Remove redundant discretization tests from StateSpaceUtilTest (#3689)
c0cb545b4 [wpilibc] Add deprecated Doxygen attribute to SpeedController (#3691)
35c9f66a7 [wpilib] Rename PneumaticsHub to PneumaticHub (#3686)
796d03d10 [wpiutil] Remove unused LLVM header (#3688)
8723caf78 [wpilibj] Make Java TrapezoidProfile.Constraints an immutable class (#3687)
187f50a34 [wpimath] Catch incorrect parameters to state-space models earlier (#3680)
8d04606c4 Replace instances of frc-characterization with SysId (NFC) (#3681)
b82d4f6e5 [hal, cscore, ntcore] Use WPI common handle type base
87e34967e [wpiutil] Add synchronization primitives
e32499c54 [wpiutil] Add ParallelTcpConnector (#3655)
aa0b49228 [wpilib] Remove redundant "quick turn" docs for curvature drive (NFC) (#3674)
57301a7f9 [hal] REVPH: Start closed-loop compressor control on init (#3673)
d1842ea8f [wpilib] Improve interrupt docs (NFC) (#3679)
558151061 [wpiutil] Add DsClient (#3654)
181723e57 Replace `.to<double>()` and `.template to<double>()` with `.value()` (#3667)
6bc1db44b [commands] Add pointer overload of AddRequirements (artf6003) (#3669)
737b57ed5 [wpimath] Update to drake v0.35.0 (#3665)
4d287d1ae [build] Upgrade WPIJREArtifact to JRE 2022-11.0.12u5 (#3666)
f26eb5ada [hal] Fix another typo (get -> gets) (NFC) (#3663)
94ed275ba [hal] Fix misspelling (numer -> number) (NFC) (#3662)
ac2f44da3 [wpiutil] uv: use move for std::function (#3653)
75fa1fbfb [wpiutil] json::serializer: Optimize construction (#3647)
5e689faea [wpiutil] Import MessagePack implementation (mpack) (#3650)
649a50b40 [wpiutil] Add LEB128 byte-by-byte reader (#3652)
e94397a97 [wpiutil] Move json_serializer.h to public headers (#3646)
4ec58724d [wpiutil] uv::Tcp: Clarify SetNoDelay documentation (#3649)
8cb294aa4 [wpiutil] WebSocket: Make Shutdown() public (#3651)
2b3a9a52b [wpiutil] json: Fix map iterator key() for std::string_view (#3645)
138cbb94b [wpiutil] uv::Async: Add direct call for no-parameter specialization (#3648)
e56d6dea8 [ci] Update testbench pool image to ubuntu-latest (#3643)
43f30e44e [build] Enable comments in doxygen source files (#3644)
9e6db17ef [build] Enable doxygen preprocessor expansion of WPI_DEPRECATED (#3642)
0e631ad2f Add WPILib version to issue template (#3641)
6229d8d2f [build] Docs: set case_sense_names to false (#3392)
4647d09b5 [docs] Fix Doxygen warnings, add CI docs lint job (#3639)
4ad3a5402 [hal] Fix PWM allocation channel (#3637)
05e5feac4 [docs] Fix brownout docs (NFC) (#3638)
67df469c5 [examples] Remove old command-based templates and examples (#3263)
689e9ccfb [hal, wpilib] Add brownout voltage configuration (#3632)
9cd4bc407 [docs] Add useLocal to avoid using installer artifacts (#3634)
61996c2bb [cscore] Fix Java direct callback notifications (#3631)
6d3dd99eb [build] Update to newest native-utils (#3633)
f0b484892 [wpiutil] Fix StringMap iterator equality check (#3629)
8352cbb7a Update development build instructions for 2022 (#3616)
6da08b71d [examples] Fix Intermediate Vision Java Example description (#3628)
5d99059bf [wpiutil] Remove optional.h (#3627)
fa41b106a [glass, wpiutil] Add missing format args (#3626)
4e3fd7d42 [build] Enable Zc:__cplusplus for Windows (#3625)
791d8354d [build] Suppress deprecation/removal warnings for old commands (#3618)
10f19e6fc [hal, wpilib] Add REV PneumaticsHub (#3600)
4c61a1305 [ntcore] Revert to per-element copy for toNative() (#3621)
7b3f62244 [wpiutil] SendableRegistry: Print exception stacktrace (#3620)
d347928e4 [hal] Use better error for when console out is enabled while attempting to use onboard serial port (#3622)
cc31079a1 [hal] Use setcap instead of setuid for setting thread priorities (#3613)
4676648b7 [wpimath] Upgrade to Drake v0.34.0 (#3607)
c7594c911 [build] Allow building wpilibc in cmake without cscore and opencv (#3605)
173cb7359 [wpilib] Add TimesliceRobot (#3502)
af295879f [hal] Set error status for I2C port out of range (#3603)
95dd20a15 [build] Enable spotbugs (#3601)
b65fce86b [wpilib] Remove Timer lock in wpilibj and update docs (#3602)
3b8d3bbcb Remove unused and add missing deprecated.h includes (#3599)
f9e976467 [examples] Rename DriveTrain classes to Drivetrain (#3594)
118a27be2 [wpilib] Add Timer tests (#3595)
59c89428e [wpilib] Deprecate Timer::HasPeriodPassed() (#3598)
202ca5e78 Force C++17 in .clang-format (#3597)
d6f185d8e Rename tests for consistency (#3592)
54ca474db [ci] Enable asan and tsan in CI for tests that pass (#3591)
1ca383b23 Add Debouncer (#3590)
179fde3a7 [build] Update to 2022 native utils and gradle 7 (#3588)
50198ffcf [examples] Add Mechanism2d visualization to Elevator Sim (#3587)
a446c2559 [examples] Synchronize C++ and Java Mechanism2d examples (#3589)
a7fb83103 [ci] clang-tidy: Generate compilation commands DB with Gradle (#3585)
4f5e0c9f8 [examples] Update ArmSimulation example to use Mechanism2d (#3572)
8164b91dc [CI] Print CMake test output on failure (#3583)
4d5fca27e [wpilib] Impove Mechanism2D documentation (NFC) (#3584)
fe59e4b9f Make C++ test names more consistent (#3586)
5c8868549 [wpilibc] Fix C++ MechanisimRoot2D to use same NT entries as Java/Glass (#3582)
9359431ba [wpimath] Clean up Eigen usage
72716f51c [wpimath] Upgrade to Eigen 3.4
382deef75 [wpimath] Explicitly export wpimath symbols
161e21173 [ntcore] Match standard handle layout, only allow 16 instances (#3577)
263a24811 [wpimath] Use jinja for codegen (#3574)
725251d29 [wpilib] Increase tolerances of DifferentialDriveSimTest (#3581)
4dff87301 [wpimath] Make LinearFilter::Factorial() constexpr (#3579)
60ede67ab [hal, wpilib] Switch PCM to be a single object that is allowed to be duplicated (#3475)
906bfc846 [build] Add CMake build support for sanitizers (#3576)
0d4f08ad9 [hal] Simplify string copy of joystick name (#3575)
a52bf87b7 [wpiutil] Add Java function package (#3570)
40c7645d6 [wpiutil] UidVector: Return old object from erase() (#3571)
5b886a23f [wpiutil] jni_util: Add size, operator[] to JArrayRef (#3569)
65797caa7 [sim] Fix halsim_ds_socket stringop overflow warning from GCC 10 (#3568)
66abb3988 [hal] Update runtime enum to allow selecting roborio 2 (#3565)
95a12e0ee [hal] UidSetter: Don't revert euid if its already current value (#3566)
27951442b [wpimath] Use external Eigen headers only (#3564)
c42e053ae [docs] Update to doxygen 1.9.2 (#3562)
e7048c8c8 [docs] Disable doxygen linking for common words that are also classes (#3563)
d8e0b6c97 [wpilibj] Fix java async interrupts (#3559)
5e6c34c61 Update to 2022 roborio image (#3537)
828f073eb [wpiutil] Fix uv::Buffer memory leaks caught by asan (#3555)
2dd5701ac [cscore] Fix mutex use-after-free in cscore test (#3557)
531439198 [ntcore] Fix NetworkTables memory leaks caught by asan (#3556)
3d9a4d585 [wpilibc] Fix AnalogTriggerOutput memory leak reported by asan (#3554)
54eda5928 [wpiutil] Ignore ubsan vptr upcast warning in SendableHelper moves (#3553)
5a4f75c9f [wpilib] Replace Speed controller comments with motor controller (NFC) (#3551)
7810f665f [wpiutil] Fix bug in uleb128 (#3540)
697e2dd33 [wpilib] Fix errant jaguar reference in comments (NFC) (#3550)
936c64ff5 [docs] Enable -linksource for javadocs (#3549)
1ea654954 [build] Upgrade CMake build to googletest 1.11.0 (#3548)
32d9949e4 [wpimath] Move controller tests to wpimath (#3541)
01ba56a8a [hal] Replace strncpy with memcpy (#3539)
e109c4251 [build] Rename makeSim flag to forceGazebo to better describe what it does (#3535)
e4c709164 [docs] Use a doxygen theme and add logo (#3533)
960b6e589 [wpimath] Fix Javadoc warning (#3532)
82eef8d5e [hal] Remove over current fault HAL functions from REV PDH (#3526)
aa3848b2c [wpimath] Move RobotDriveBase::ApplyDeadband() to MathUtil (#3529)
3b5d0d141 [wpimath] Add LinearFilter::BackwardFiniteDifference() (#3528)
c8fc715fe [wpimath] Upgrade drake files to v0.33.0 (#3531)
e5fe3a8e1 [build] Treat javadoc warnings as errors in CI and fix warnings (#3530)
e0c6cd3dc [wpimath] Add an operator for composing two Transform2ds (#3527)
2edd510ab [sim] Add sim wrappers for sensors that use SimDevice (#3517)
2b3e2ebc1 [hal] Fix HAL Notifier thread priority setting (#3522)
ab4cb5932 [gitignore] Update gitignore to ignore bazel / clion files (#3524)
57c8615af [build] Generate spotless patch on failure (#3523)
b90317321 Replace std::cout and std::cerr with fmt::print() (#3519)
10cc8b89c [hal] [wpilib] Add initial support for the REV PDH (#3503)
5d9ae3cdb [hal] Set HAL Notifier thread as RT by default (#3482)
192d251ee [wpilibcIntegrationTests] Properly disable DMA integration tests (#3514)
031962608 [wpilib] Add PS4Controller, remove Hand from GenericHID/XboxController (#3345)
25f6f478a [wpilib] Rename DriverStation::IsOperatorControl() to IsTeleop() (#3505)
e80f09f84 [wpilibj] Add unit tests (#3501)
c159f91f0 [wpilib] Only read DS control word once in IterativeRobotBase (#3504)
eb790a74d Add rio development docs documenting myRobot deploy tasks (#3508)
e47451f5a [wpimath] Replace auto with Eigen types (#3511)
252b8c83b Remove Java formatting from build task in CI (#3507)
09666ff29 Shorten Gazebo CI build (#3506)
baf2e501d Update myRobot to use 2021 java (#3509)
5ac60f0a2 [wpilib] Remove IterativeRobotBase mode init prints (#3500)
fb2ee8ec3 [wpilib] Add TimedRobot functions for running code on mode exit (#3499)
94e0db796 [wpilibc] Add more unit tests (#3494)
b25324695 [wpilibj] Add units to parameter names (NFC) (#3497)
1ac73a247 [hal] Rename PowerDistributionPanel to PowerDistribution (#3466)
2014115bc [examples] frisbeebot: Fix typo and reflow comments (NFC) (#3498)
4a944dc39 [examples] Consistently use 0 for controller port (#3496)
3838cc4ec Use unicode characters in docs equations (#3487)
85748f2e6 [examples] Add C++ TankDrive example (#3493)
d7b8aa56d [wpilibj] Rename DriverStation In[Mode] functions to follow style guide (#3488)
16e096cf8 [build] Fix CMake Windows CI (#3490)
50af74c38 [wpimath] Clean up NumericalIntegration and add Discretization tests (#3489)
bfc209b12 Automate fmt update (#3486)
e7f9331e4 [build] Update to Doxygen 1.9.1 (#3008)
ab8e8aa2a [wpimath] Update drake with upstream (#3484)
1ef826d1d [wpimath] Fix IOException path in WPIMath JNI (#3485)
52bddaa97 [wpimath] Disable iostream support for units and enable fmtlib (#3481)
e4dc3908b [wpiutil] Upgrade to fmtlib 8.0.1 (#3483)
1daadb812 [wpimath] Implement Dormand-Prince integration method (#3476)
9c2723391 [cscore] Add [[nodiscard]] to GrabFrame functions (#3479)
7a8796414 [wpilib] Add Notifier integration tests (#3480)
f8f13c536 [wpilibcExamples] Prefix decimal numbers with 0 (#3478)
1adb69c0f [ntcore] Use "NetworkTables" instead of "Network Tables" in NT specs (#3477)
5f5830b96 Upload wpiformat diff if one exists (#3474)
9fb4f35bb [wpimath] Add tests for DARE overload with Q, R, and N matrices (#3472)
c002e6f92 Run wpiformat (#3473)
c154e5262 [wpilib] Make solenoids exclusive use, PCM act like old sendable compressor (#3464)
6ddef1cca [hal] JNI setDIO: use a boolean and not a short (#3469)
9d68d9582 Remove extra newlines after open curly braces (NFC) (#3471)
a4233e1a1 [wpimath] Add script for updating Drake (#3470)
39373c6d2 Update README.md for new GCC version requirement (#3467)
d29acc90a [wpigui] Add option to reset UI on exit (#3463)
a371235b0 [ntcore] Fix dangling pointer in logger (#3465)
53b4891a5 [wpilibcintegrationtests] Fix deprecated Preferences usage (#3461)
646ded912 [wpimath] Remove incorrect discretization in pose estimators (#3460)
ea0b8f48e Fix some deprecation warnings due to fmtlib upgrade (#3459)
2067d7e30 [wpilibjexamples] Add wpimathjni, wpiutiljni to library path (#3455)
866571ab4 [wpiutil] Upgrade to fmtlib 8.0.0 (#3457)
4e1fa0308 [build] Skip PDB copy on windows build servers (#3458)
b45572167 [build] Change CI back to 18.04 docker images (#3456)
57a160f1b [wpilibc] Fix LiveWindow deprecation warning in RobotBase skeleton template (#3454)
29ae8640d [HLT] Implement duty cycle cross connect tests (#3453)
ee6377e54 [HLT] Add relay and analog cross connects (#3452)
b0f1ae7ea [build] CMake: Build the HAL even if WITH_CSCORE=OFF (#3449)
7aae2b72d Replace std::to_string() with fmt::format() (#3451)
73fcbbd74 [HLT] Add relay digital cross connect tests (#3450)
e7bedde83 [HLT] Add PWM tests that use DMA as the back end (#3447)
7253edb1e [wpilibc] Timer: Fix deprecated warning (#3446)
efa28125c [wpilibc] Add message to RobotBase on how to read stacktrace (#3444)
9832fcfe1 [hal] Fix DIO direction getter (#3445)
49c71f9f2 [wpilibj] Clarify robot quit message (#3364)
791770cf6 [wpimath] Move controller from wpilibj to wpimath (#3439)
9ce9188ff [wpimath] Add ReportWarning to MathShared (#3441)
362066a9b [wpilib] Deprecate getInstance() in favor of static functions (#3440)
26ff9371d Initial commit of cross connect integration test project (#3434)
4a36f86c8 [hal] Add support for DMA to Java (#3158)
85144e47f [commands] Unbreak build (#3438)
b417d961e Split Sendable into NT and non-NT portions (#3432)
ef4ea84cb [commands] Change grouping decorator impl to flatten nested group structures (#3335)
b422665a3 [examples] Invert right side of drive subsystems (#3437)
186dadf14 [hal] Error if attempting to set DIO output on an input port (#3436)
04e64db94 Remove redundant C++ lambda parentheses (NFC) (#3433)
f60994ad2 [wpiutil] Rename Java package to edu.wpi.first.util (#3431)
cfa1ca96f [wpilibc] Make ShuffleboardValue non-copyable (#3430)
4d9ff7643 Fix documentation warnings generated by JavaDoc (NFC) (#3428)
9e1b7e046 [build] Fix clang-tidy and clang-format (#3429)
a77c6ff3a [build] Upgrade clang-format and clang-tidy (NFC) (#3422)
099fde97d [wpilib] Improve PDP comments (NFC) (#3427)
f8fc2463e [wpilibc, wpiutil] Clean up includes (NFC) (#3426)
e246b7884 [wpimath] Clean up member initialization in feedforward classes (#3425)
c1e128bd5 Disable frivolous PMD warnings and enable PMD in ntcore (#3419)
8284075ee Run "Lint and Format" CI job on push as well as pull request (#3412)
f7db09a12 [wpimath] Move C++ filters into filter folder to match Java (#3417)
f9c3d54bd [wpimath] Reset error covariance in pose estimator ResetPosition() (#3418)
0773f4033 [hal] Ensure HAL status variables are initialized to zero (#3421)
d068fb321 [build] Upgrade CI to use 20.04 docker images (#3420)
8d054c940 [wpiutil] Remove STLExtras.h
80f1d7921 [wpiutil] Split function_ref to a separate header
64f541325 Use wpi::span instead of wpi::ArrayRef across all libraries (#3414)
2abbbd9e7 [build] clang-tidy: Remove bugprone-exception-escape (#3415)
a5c471af7 [wpimath] Add LQR template specialization for 2x2 system
edd2f0232 [wpimath] Add DARE solver for Q, R, and N with LQR ctor overloads
b2c3b2dd8 Use std::string_view and fmtlib across all libraries (#3402)
4f1cecb8e [wpiutil] Remove Path.h (#3413)
b336eac34 [build] Publish halsim_ws_core to Maven
2a09f6fa4 [build] Also build sim modules as static libraries
0e702eb79 [hal] Add a unified PCM object (#3331)
dea841103 [wpimath] Add fmtlib formatter overloads for Eigen::Matrix and units (#3409)
82856cf81 [wpiutil] Improve wpi::circular_buffer iterators (#3410)
8aecda03e [wpilib] Fix a documentation typo (#3408)
5c817082a [wpilib] Remove InterruptableSensorBase and replace with interrupt classes (#2410)
15c521a7f [wpimath] Fix drivetrain system identification (#3406)
989de4a1b [build] Force all linker warnings to be fatal for rio builds (#3407)
d9eeb45b0 [wpilibc] Add units to Ultrasonic class API (#3403)
fe570e000 [wpiutil] Replace llvm filesystem with C++17 filesystem (#3401)
01dc0249d [wpimath] Move SlewRateLimiter from wpilib to wpimath (#3399)
93523d572 [wpilibc] Clean up integration tests (#3400)
4f7a4464d [wpiutil] Rewrite StringExtras for std::string_view (#3394)
e09293a15 [wpilibc] Transition C++ classes to units::second_t (#3396)
827b17a52 [build] Create run tasks for Glass and OutlineViewer (#3397)
a61037996 [wpiutil] Avoid MSVC warning on span include (#3393)
4e2c3051b [wpilibc] Use std::string_view instead of Twine (#3380)
50915cb7e [wpilibc] MotorSafety::GetDescription(): Return std::string (#3390)
f4e2d26d5 [wpilibc] Move NullDeleter from frc/Base.h to wpi/NullDeleter.h (#3387)
cb0051ae6 [wpilibc] SimDeviceSim: use fmtlib (#3389)
a238cec12 [wpiutil] Deprecate wpi::math constants in favor of wpi::numbers (#3383)
393bf23c0 [ntcore, cscore, wpiutil] Standardize template impl files on .inc extension (NFC) (#3124)
e7d9ba135 [sim] Disable flaky web server integration tests (#3388)
0a0003c11 [wpilibjExamples] Fix name of Java swerve drive pose estimator example (#3382)
7e1b27554 [wpilibc] Use default copies and moves when possible (#3381)
fb2a56e2d [wpilibc] Remove START_ROBOT_CLASS macro (#3384)
84218bfb4 [wpilibc] Remove frc namespace shim (#3385)
dd7824340 [wpilibc] Remove C++ compiler version static asserts (#3386)
484cf9c0e [wpimath] Suppress the -Wmaybe-uninitialized warning in Eigen (#3378)
a04d1b4f9 [wpilibc] DriverStation: Remove ReportError and ReportWarning
831c10bdf [wpilibc] Errors: Use fmtlib
87603e400 [wpiutil] Import fmtlib (#3375)
442621672 [wpiutil] Add ArrayRef/std::span/wpi::span implicit conversions
bc15b953b [wpiutil] Add std::span implementation
6d20b1204 [wpiutil] StringRef, Twine, raw_ostream: Add std::string_view support (#3373)
2385c2a43 [wpilibc] Remove Utility.h (#3376)
87384ea68 [wpilib] Fix PIDController continuous range error calculations (#3170)
04dae799a [wpimath] Add SimpleMotorFeedforward::Calculate(velocity, nextVelocity) overload (#3183)
0768c3903 [wpilib] DifferentialDrive: Remove right side inversion (#3340)
8dd8d4d2d [wpimath] Fix redundant nested math package introduced by #3316 (#3368)
49b06beed [examples] Add Field2d to RamseteController example (#3371)
4c562a445 [wpimath] Fix typo in comment of update_eigen.py (#3369)
fdbbf1188 [wpimath] Add script for updating Eigen
f1e64b349 [wpimath] Move Eigen unsupported folder into eigeninclude
224f3a05c [sim] Fix build error when building with GCC 11.1 (#3361)
ff56d6861 [wpilibj] Fix SpeedController deprecated warnings (#3360)
1873fbefb [examples] Fix Swerve and Mecanum examples (#3359)
80b479e50 [examples] Fix SwerveBot example to use unique encoder ports (#3358)
1f7c9adee [wpilibjExamples] Fix pose estimator examples (#3356)
9ebc3b058 [outlineviewer] Change default size to 600x400 (#3353)
e21b443a4 [build] Gradle: Make C++ examples runnable (#3348)
da590120c [wpilibj] Add MotorController.setVoltage default (#3347)
561d53885 [build] Update opencv to 4.5.2, imgui/implot to latest (#3344)
44ad67ca8 [wpilibj] Preferences: Add missing Deprecated annotation (#3343)
3fe8fc75a [wpilibc] Revert "Return reference from GetInstance" (#3342)
3cc2da332 Merge branch '2022'
a3cd90dd7 [wpimath] Fix classpath used by generate_numbers.py (#3339)
d6cfdd3ba [wpilib] Preferences: Deprecate Put* in favor of Set* (#3337)
ba08baabb [wpimath] Update Drake DARE solver to v0.29.0 (#3336)
497b712f6 [wpilib] Make IterativeRobotBase::m_period private with getter
f00dfed7a [wpilib] Remove IterativeRobot base class
3c0846168 [hal] Use last error reporting instead of PARAMETER_OUT_OF_RANGE (#3328)
5ef2b4fdc [wpilibj] Fix @deprecated warning for SerialPort constructor (#3329)
23d2326d1 [hal] Report previous allocation location for indexed resource duplicates (#3322)
e338f9f19 [build] Fix wpilibc runCpp task (#3327)
c8ff626fe [wpimath] Move Java classes to edu.wpi.first.math (#3316)
4e424d51f [wpilibj] DifferentialDrivetrainSim: Rename constants to match the style guide (#3312)
6b50323b0 [cscore] Use Lock2DSize if possible for Windows USB cameras (#3326)
65c148536 [wpilibc] Fix "control reaches end of non-void function" warning (#3324)
f99f62bee [wpiutil] uv Handle: Use malloc/free instead of new/delete (#3325)
365f5449c [wpimath] Fix MecanumDriveKinematics (#3266)
ff52f207c [glass, wpilib] Rewrite Mechanism2d (#3281)
ee0eed143 [wpimath] Add DCMotor factory function for Romi motors (#3319)
512738072 [hal] Add HAL_GetLastError to enable better error messages from HAL calls (#3320)
ced654880 [glass, outlineviewer] Update Mac icons to macOS 11 style (#3313)
936d3b9f8 [templates] Add Java template for educational robot (#3309)
6e31230ad [examples] Fix odometry update in SwerveControllerCommand example (#3310)
05ebe9318 Merge branch 'main' into 2022
aaf24e255 [wpilib] Fix initial heading behavior in HolonomicDriveController (#3290)
8d961dfd2 [wpilibc] Remove ErrorBase (#3306)
659b37ef9 [wpiutil] StackTrace: Include offset on Linux (#3305)
0abf6c904 [wpilib] Move motor controllers to motorcontrol package (#3302)
4630191fa [wpiutil] circular_buffer: Use value initialization instead of passing zero (#3303)
b7b178f49 [wpilib] Remove Potentiometer interface
687066af3 [wpilib] Remove GyroBase
6b168ab0c [wpilib] Remove PIDController, PIDOutput, PIDSource
948625de9 [wpimath] Document conversion from filter cutoff frequency to time constant (#3299)
3848eb8b1 [wpilibc] Fix flywhel -> flywheel typo in FlywheelSim (#3298)
3abe0b9d4 [cscore] Move java package to edu.wpi.first.cscore (#3294)
d7fabe81f [wpilib] Remove RobotDrive (#3295)
1dc81669c [wpilib] Remove GearTooth (#3293)
01d0e1260 [wpilib] Revert move of RomiGyro into main wpilibc/j (#3296)
397e569aa [ntcore] Remove "using wpi" from nt namespace
79267f9e6 [ntcore] Remove NetworkTable -> nt::NetworkTable shim
48ebe5736 [ntcore] Remove deprecated Java interfaces and classes
c2064c78b [ntcore] Remove deprecated ITable interfaces
36608a283 [ntcore] Remove deprecated C++ APIs
a1c87e1e1 [glass] LogView: Add "copy to clipboard" button (#3274)
fa7240a50 [wpimath] Fix typo in quintic spline basis matrix
ffb4d38e2 [wpimath] Add derivation for spline basis matrices
f57c188f2 [wpilib] Add AnalogEncoder(int) ctor (#3273)
8471c4fb2 [wpilib] FieldObject2d: Add setTrajectory() method (#3277)
c97acd18e [glass] Field2d enhancements (#3234)
ffb590bfc [wpilib] Fix Compressor sendable properties (#3269)
6137f98eb [hal] Rename SimValueCallback2 to SimValueCallback (#3212)
a6f653969 [hal] Move registerSimPeriodic functions to HAL package (#3211)
10c038d9b [glass] Plot: Fix window creation after removal (#3264)
2d2eaa3ef [wpigui] Ensure window will be initially visible (#3256)
4d28b1f0c [wpimath] Use JNI for trajectory serialization (#3257)
3de800a60 [wpimath] TrajectoryUtil.h: Comment formatting (NFC) (#3262)
eff592377 [glass] Plot: Don't overwrite series ID (#3260)
a79faace1 [wpilibc] Return reference from GetInstance (#3247)
9550777b9 [wpilib] PWMSpeedController: Use PWM by composition (#3248)
c8521a3c3 [glass] Plot: Set reasonable default window size (#3261)
d71eb2cf3 [glass] Plot: Show full source name as tooltip and in popup (#3255)
160fb740f [hal] Use std::lround() instead of adding 0.5 and truncating (#3012)
48e9f3951 [wpilibj] Remove wpilibj package CameraServer (#3213)
8afa596fd [wpilib] Remove deprecated Sendable functions and SendableBase (#3210)
d3e45c297 [wpimath] Make C++ geometry classes immutable (#3249)
2c98939c1 [glass] StringChooser: Don't call SameLine() at end
a18a7409f [glass] NTStringChooser: Clear value of deleted entries
2f19cf452 [glass] NetworkTablesHelper: listen to delete events
da96707dc Merge branch 'main' into 2022
c3a8bdc24 [build] Fix clang-tidy action (#3246)
21624ef27 Add ImGui OutlineViewer (#3220)
1032c9b91 [wpiutil] Unbreak wpi::Format on Windows (#3242)
2e07902d7 [glass] NTField2D: Fix name lookup (#3233)
6e23e1840 [wpilibc] Remove WPILib.h (#3235)
3e22e4506 [wpilib] Make KoP drivetrain simulation weight 60 lbs (#3228)
79d1bd6c8 [glass] NetworkTablesSetting: Allow disable of server option (#3227)
fe341a16f [examples] Use more logical elevator setpoints in GearsBot (#3198)
62abf46b3 [glass] NetworkTablesSettings: Don't block GUI (#3226)
a95a5e0d9 [glass] Move NetworkTablesSettings to libglassnt (#3224)
d6f6ceaba [build] Run Spotless formatter (NFC) (#3221)
0922f8af5 [commands] CommandScheduler.requiring(): Note return can be null (NFC) (#2934)
6812302ff [examples] Make DriveDistanceOffboard example work in sim (#3199)
f3f86b8e7 [wpimath] Add pose estimator overload for vision + std dev measurement (#3200)
1a2680b9e [wpilibj] Change CommandBase.withName() to return CommandBase (#3209)
435bbb6a8 [command] RamseteCommand: Output 0 if interrupted (#3216)
3cf44e0a5 [hal] Add function for changing HAL Notifier thread priority (#3218)
40b367513 [wpimath] Units.java: Add kg-lb conversions (#3203)
9f563d584 [glass] NT: Fix return value in StringToDoubleArray (#3208)
af4adf537 [glass] Auto-size plots to fit window (#3193)
2560146da [sim] GUI: Add option to show prefix in Other Devices (#3186)
eae3a6397 gitignore: Ignore .cache directory (#3196)
959611420 [wpilib] Require non-zero positive value for PIDController.period (#3175)
9522f2e8c [wpimath] Add methods to concatenate trajectories (#3139)
e42a0b6cf [wpimath] Rotation2d comment formatting (NFC) (#3162)
d1c7032de [wpimath] Fix order of setting gyro offset in pose estimators (#3176)
d241bc81a [sim] Add DoubleSolenoidSim and SolenoidSim classes (#3177)
cb7f39afa [wpilibc] Add RobotController::GetBatteryVoltage() to C++ (#3179)
99b5ad9eb [wpilibj] Fix warnings that are not unused variables or deprecation (#3161)
c14b23775 [build] Fixup doxygen generated include dirs to match what users would need (#3154)
d447c7dc3 [sim] Add SimDeviceSim ctor overloads (#3134)
247420c9c [build] Remove jcenter repo (#3157)
04b112e00 [build] Include debug info in plugin published artifacts (#3149)
be0ce9900 [examples] Use PWMSparkMax instead of PWMVictorSPX (#3156)
69e8d0b65 [wpilib] Move RomiGyro into main wpilibc/j (#3143)
94e685e1b [wpimath] Add custom residual support to EKF (#3148)
5899f3dd2 [sim] GUI: Make keyboard settings loading more robust (#3167)
f82aa1d56 [wpilib] Fix HolonomicDriveController atReference() behavior (#3163)
fe5c2cf4b [wpimath] Remove ControllerUtil.java (#3169)
43d40c6e9 [wpiutil] Suppress unchecked cast in CombinedRuntimeLoader (#3155)
3d44d8f79 [wpimath] Fix argument order in UKF docs (NFC) (#3147)
ba6fe8ff2 [cscore] Add USB camera change event (#3123)
533725888 [build] Tweak OpenCV cmake search paths to work better on Linux (#3144)
29bf9d6ef [cscore] Add polled support to listener
483beb636 [ntcore] Move CallbackManager to wpiutil
fdaec7759 [examples] Instantiate m_ramseteController in example (#3142)
8494a5761 Rename default branch to main (#3140)
45590eea2 [wpigui] Hardcode window scale to 1 on macOS (#3135)
834a64920 [build] Publish libglass and libglassnt to Maven (#3127)
2c2ccb361 [wpimath] Fix Rotation2d equality operator (#3128)
fb5c8c39a [wpigui] clang-tidy: readability-braces-around-statements
f7d39193a [wpigui] Fix copyright in pfd and wpigui_metal.mm
aec796b21 [ntcore] Fix conditional jump on uninitialized value (#3125)
fb13bb239 [sim] GUI: Add right click popup for keyboard joystick settings (#3119)
c517ec677 [build] Update thirdparty-imgui to 1.79-2 (#3118)
e8cbf2a71 [wpimath] Fix typo in SwerveDrivePoseEstimator doc (NFC) (#3112)
e9c86df46 [wpimath] Add tests for swerve module optimization (#3100)
6ba8c289c [examples] Remove negative of ArcadeDrive(fwd, ..) in the C++ Getting Started Example (#3102)
3f1672e89 [hal] Add SimDevice createInt() and createLong() (#3110)
15be5cbf1 [examples] Fix segfault in GearsBot C++ example (#3111)
4cf0e5e6d Add quick links to API documentation in README (#3082)
6b1898f12 Fix RT priority docs (NFC) (#3098)
b3426e9c0 [wpimath] Fix missing whitespace in pose estimator doc (#3097)
38c1a1f3e [examples] Fix feildRelative -> fieldRelative typo in XControllerCommand examples (#3104)
4488e25f1 [glass] Shorten SmartDashboard window names (#3096)
cfdb3058e [wpilibj] Update SimDeviceSimTest (#3095)
64adff5fe [examples] Fix typo in ArcadeDrive constructor parameter name (#3092)
6efc58e3d [build] Fix issues with build on windows, deprecations, and native utils (#3090)
f393989a5 [wpimath, wpiutil] Add wpi::array for compile time size checking (#3087)
d6ed20c1e [build] Set macOS deployment target to 10.14 (#3088)
7c524014c [hal] Add [[nodiscard]] to HAL_WaitForNotifierAlarm() (#3085)
406d055f0 [wpilib] Fixup wouldHitLowerLimit in elevator and arm simulation classes. (#3076)
04a90b5dd [examples] Don't continually set setpoint in PotentiometerPID Examples (#3084)
8c5bfa013 [sim] GUI: Add max value setting for keyboard joysticks (#3083)
bc80c5535 [hal] Add SimValue reset() function (#3064)
9c3b51ca0 [wpilib] Document simulation APIs (#3079)
26584ff14 [wpimath] Add model description to LinearSystemId Javadocs (#3080)
42c3d5286 [examples] Sync Java and C++ trajectories in sim example (#3081)
64e72f710 [wpilibc] Add missing function RoboRioSim::ResetData (#3073)
e95503798 [wpimath] Add optimize() to SwerveModuleState (#3065)
fb99910c2 [hal] Add SimInt and SimLong wrappers for int/long SimValue (#3066)
e620bd4d3 [doc] Add machine-readable websocket specification (#3059)
a44e761d9 [glass] Add support for plot Y axis labels
ea1974d57 [wpigui] Update imgui and implot to latest
85a0bd43c [wpimath] Add RKF45 integration (#3047)
278e0f126 [glass] Use .controllable to set widgets' read-only state (#3035)
d8652cfd4 [wpimath] Make Java DCMotor API consistent with C++ and fix motor calcs (#3046)
377b7065a [build] Add toggleOffOn to Java spotless (#3053)
1e9c79c58 [sim] Use plant output to retrieve simulated position (#3043)
78147aa34 [sim] GUI: Fix Keyboard Joystick (#3052)
cd4a2265b [ntcore] Fix NetworkTableEntry::GetRaw() (#3051)
767ac1de1 [build] Use deploy key for doc publish (#3048)
d762215d1 [build] Add publish documentation script (#3040)
1fd09593c [examples] Add missing TestInit method to GettingStarted Example (#3039)
e45a0f6ce [examples] Add RomiGyro to the Romi Reference example (#3037)
94f852572 Update imaging link and fix typo (#3038)
d73cf64e5 [examples] Update RomiReference to match motor directions (#3036)
f945462ba Bump copyright year to 2021 (#3033)
b05946175 [wpimath] Catch Drake JNI exceptions and rethrow them (#3032)
62f0f8190 [wpimath] Deduplicate angle modulus functions (#2998)
bf8c0da4b [glass] Add "About" popup with version number (#3031)
dfdd6b389 [build] Increase Gradle heap size in Gazebo build (#3028)
f5e0fc3e9 Finish clang-tidy cleanups (#3003)
d741101fe [sim] Revert accidental commit of WSProvider_PDP.h (#3027)
e1620799c [examples] Add C++ RomiReference example (#2969)
749c7adb1 [command] Fix use-after-free in CommandScheduler (#3024)
921a73391 [sim] Add WS providers for AddressableLED, PCM, and Solenoid (#3026)
26d0004fe [build] Split Actions into different yml files (#3025)
948af6d5b [wpilib] PWMSpeedController.get(): Apply Inversion (#3016)
670a187a3 [wpilibc] SuppliedValueWidget.h: Forward declare ShuffleboardContainer (#3021)
be9f72502 [ntcore] NetworkTableValue: Use std::forward instead of std::move (#3022)
daf3f4cb1 [cscore] cscore_raw_cv.h: Fix error in PutFrame() (#3019)
5acda4cc7 [wpimath] ElevatorFeedforward.h: Add time.h include
8452af606 [wpimath] units/radiation.h: Add mass.h include
630d44952 [hal] ErrorsInternal.h: Add stdint.h include
7372cf7d9 [cscore] Windows NetworkUtil.cpp: Add missing include
b7e46c558 Include .h from .inc/.inl files (NFC) (#3017)
bf8f8710e [examples] Update Romi template and example (#2996)
6ffe5b775 [glass] Ensure NetworkTableTree parent context menu has an id (#3015)
be0805b85 [build] Update to WPILibVersioningPlugin 4.1.0 (#3014)
65b2359b2 [build] Add spotless for other files (#3007)
8651aa73e [examples] Enable NT Flush in Field2d examples (#3013)
78b542737 [build] Add Gazebo build to Actions CI (#3004)
fccf86532 [sim] DriverStationGui: Fix two bugs (#3010)
185741760 [sim] WSProvider_Joystick: Fix off-by-1 in incoming buttons (#3011)
ee7114a58 [glass] Add drive class widgets (#2975)
00fa91d0d [glass] Use ImGui style for gyro widget colors (#3009)
b7a25bfc3 ThirdPartyNotices: Add portable file dialogs license (#3005)
a2e46b9a1 [glass] modernize-use-nullptr (NFC) (#3006)
a751fa22d [build] Apply spotless for java formatting (#1768)
e563a0b7d [wpimath] Make LinearSystemLoop move-constructible and move-assignable (#2967)
49085ca94 [glass] Add context menus to remove and add NetworkTables values (#2979)
560a850a2 [glass] Add NetworkTables Log window (#2997)
66782e231 [sim] Create Left/Right drivetrain current accessors (#3001)
b60eb1544 clang-tidy: bugprone-virtual-near-miss
cbe59fa3b clang-tidy: google-explicit-constructor
c97c6dc06 clang-tidy: google-readability-casting (NFC)
32fa97d68 clang-tidy: modernize-use-nullptr (NFC)
aee460326 clang-tidy: modernize-pass-by-value
29c7da5f1 clang-tidy: modernize-make-unique
6131f4e32 clang-tidy: modernize-concat-nested-namespaces (NFC)
67e03e625 clang-tidy: modernize-use-equals-default
b124f9101 clang-tidy: modernize-use-default-member-init
d11a3a638 clang-tidy: modernize-use-override (NFC)
4cc0706b0 clang-tidy: modernize-use-using (NFC)
885f5a978 [wpilibc] Speed up ScopedTracerTest (#2999)
60b596457 [wpilibj] Fix typos (NFC) (#3000)
6e1919414 [build] Bring naming checkstyle rules up to date with Google Style guide (#1781)
8c8ec5e63 [wpilibj] Suppress unchecked cast warnings (#2995)
b8413ddd5 [wpiutil] Add noexcept to timestamp static functions (#2994)
5d976b6e1 [glass] Load NetworkTableView settings on first draw (#2993)
2b4317452 Replace NOLINT(runtime/explicit) comments with NOLINT (NFC) (#2992)
1c3011ba4 [glass] Fix handling of "/" NetworkTables key (#2991)
574a42f3b [hal] Fix UnsafeManipulateDIO status check (#2987)
9005cd59e [wpilib] Clamp input voltage in sim classes (#2955)
dd494d4ab [glass] NetworkTablesModel::Update(): Avoid use-after-move (#2988)
7cca469a1 [wpimath] NormalizeAngle: Make inline, remove unnamed namespace (#2986)
2aed432b4 Add braces to C++ single-line loops and conditionals (NFC) (#2973)
0291a3ff5 [wpiutil] StringRef: Add noexcept to several constructors (#2984)
5d7315280 [wpimath] Update UnitsTest.cpp copyright (#2985)
254931b9a [wpimath] Remove LinearSystem from LinearSystemLoop (#2968)
aa89744c9 Update OtherVersions.md to include wpimath info (#2983)
1cda3f5ad [glass] Fix styleguide (#2976)
8f1f64ffb Remove year from file copyright message (NFC) (#2972)
2bc0a7795 [examples] Fix wpiformat warning about utility include (#2971)
4204da6ad [glass] Add application icon
7ac39b10f [wpigui] Add icon support
6b567e006 [wpimath] Add support for varying vision standard deviations in pose estimators (#2956)
df299d6ed [wpimath] Add UnscentedKalmanFilter::Correct() overload (#2966)
4e34f0523 [examples] Use ADXRS450_GyroSim class in simulation example (#2964)
9962f6fd7 [wpilib] Give Field2d a default Sendable name (#2953)
f9d492f4b [sim] GUI: Show "Other Devices" window by default (#2961)
a8bb2ef1c [sim] Fix ADXRS450_GyroSim and DutyCycleEncoderSim (#2963)
240c629cd [sim] Try to guess "Map Gamepad" setting (#2960)
952567dd3 [wpilibc] Add missing move constructors and assignment operators (#2959)
10b396b4c [sim] Various WebSockets fixes and enhancements (#2952)
699bbe21a [examples] Fix comments in Gearsbot to match implementation (NFC) (#2957)
27b67deca [glass] Add more widgets (#2947)
581b7ec55 [wpilib] Add option to flush NetworkTables every iterative loop
acfbb1a44 [ntcore] DispatcherBase::Flush: Use wpi::Now()
d85a6d8fe [ntcore] Reduce limit on flush and update rate to 5 ms
20fbb5c63 [sim] Fix stringop truncation warning from GCC 10 (#2945)
1051a06a7 [glass] Show NT timestamps in seconds (#2944)
98dfc2620 [glass] Fix plots (#2943)
1ba0a2ced [sim] GUI: Add keyboard virtual joystick support (#2940)
4afb13f98 [examples] Replace M_PI with wpi::math::pi (#2938)
b27d33675 [examples] Enhance Romi templates (#2931)
00b9ae77f [sim] Change default WS port number to 3300 (#2932)
65219f309 [examples] Update Field2d position in periodic() (#2928)
f78d1d434 [sim] Process WS Encoder reset internally (#2927)
941edca59 [hal] Add Java SimDeviceDataJNI.getSimDeviceName (#2924)
a699435ed [wpilibj] Fix FlywheelSim argument order in constructor (#2922)
66d641718 [examples] Add tasks to run Java examples (#2920)
558e37c41 [examples] Add simple differential drive simulation example (#2918)
4f40d991e [glass] Switch name of Glass back to glass (#2919)
549af9900 [build] Update native-utils to 2021.0.6 (#2914)
b33693009 [glass] Change basename of glass to Glass (#2915)
c9a0edfb8 [glass] Package macOS application bundle
2c5668af4 [wpigui] Add platform-specific preferences save
751dea32a [wpilibc] Try to work around ABI break introduced in #2901 (#2917)
cd8f4bfb1 [build] Package up msvc runtime into maven artifact (#2913)
a6cfcc686 [wpilibc] Move SendableChooser Doxygen comments to header (NFC) (#2911)
b8c4f603d [wpimath] Upgrade to Eigen 3.3.9 (#2910)
0075e4b39 [wpilibj] Fix NPE in Field2d (#2909)
125af556c [simulation] Fix halsim_gui ntcore and wpiutil deps (#2908)
963ad5c25 [wpilib] Add noise to Differential Drive simulator (#2903)
387f56cb7 [examples] Add Romi reference Java example and templates (#2905)
b3deda38c [examples] Zero motors on disabledInit() in sim physics examples (#2906)
2a5ca7745 [glass] Add glass: an application for display of robot data
727940d84 [wpilib] Move Field2d to SmartDashboard
8cd42478e [wpilib] SendableBuilder: Make GetTable() visible
c11d34b26 [command] Use addCommands in command group templates (#2900)
339d7445b [sim] Add HAL hooks for simulationPeriodic (#2881)
d16f05f2c [wpilib] Fix SmartDashboard update order (#2896)
5427b32a4 [wpiutil] unique_function: Restrict implicit conversion (#2899)
f73701239 [ntcore] Add missing SetDefault initializer_list functions (#2898)
f5a6fc070 [sim] Add initialized flag for all solenoids on a PCM (#2897)
bdf5ba91a [wpilibj] Fix typo in ElevatorSim (#2895)
bc8f33877 [wpilib] Add pose estimators (#2867)
3413bfc06 [wpilib] PIDController: Recompute the error in AtSetpoint() (#2822)
2056f0ce0 [wpilib] Fix bugs in Hatchbot examples (#2893)
5eb8cfd69 [wpilibc] Fix MatchDataSender (#2892)
e6a425448 [build] Delete test folders after tests execute (#2891)
d478ad00d [imgui] Allow usage of imgui_stdlib (#2889)
53eda861d [build] Add unit-testing infrastructure to examples (#2863)
cc1d86ba6 [sim] Add title to simulator GUI window (#2888)
f0528f00e [build] CMake: Use project-specific binary and source dirs (#2886)
5cd2ad124 [wpilibc] Add Color::operator!= (#2887)
6c00e7a90 [build] CI CMake: build with GUI enabled (#2884)
53170bbb5 Update roboRIO toolchain installation instructions (#2883)
467258e05 [sim] GUI: Add option to not zero disconnected joysticks (#2876)
129be23c9 Clarify JDK installation instructions in readme (#2882)
8e9290e86 [build] Add separate CMake setting for wpimath (#2885)
7cf5bebf8 [wpilibj] Cache NT writes from DriverStation (#2780)
f7f9087fb [command] Fix timing issue in RamseteCommand (#2871)
256e7904f [wpilibj] SimDeviceSim: Fix sim value changed callback (#2880)
c8ea1b6c3 [wpilib] Add function to adjust LQR controller gain for pure time delay (#2878)
2816b06c0 [sim] HAL_GetControlWord: Fully zero output (#2873)
4c695ea08 Add toolchain installation instructions to README (#2875)
a14d51806 [wpimath] DCMotor: fix doc typo (NFC) (#2868)
017097791 [build] CMake: build sim extensions as shared libs (#2866)
f61726b5a [build] Fix cmake-config files (#2865)
fc27fdac5 [wpilibc] Cache NT values from driver station (#2768)
47c59859e [sim] Make SimDevice callbacks synchronous (#2861)
6e76ab9c0 [build] Turn on WITH_GUI for Windows cmake CI
5f78b7670 [build] Set GLFW_INSTALL to OFF
5e0808c84 [wpigui] Fix Windows cmake build
508f05a47 [imgui] Fix typo in Windows CMake target sources
Change-Id: I1737b45965f31803a96676bedc7dc40e337aa321
git-subtree-dir: third_party/allwpilib
git-subtree-split: e473a00f9785f9949e5ced30901baeaf426d2fc9
Signed-off-by: Austin Schuh <austin.linux@gmail.com>
diff --git a/cscore/.styleguide b/cscore/.styleguide
index fada841..f0732e1 100644
--- a/cscore/.styleguide
+++ b/cscore/.styleguide
@@ -31,6 +31,7 @@
}
includeOtherLibs {
+ ^fmt/
^opencv2/
^support/
^tcpsockets/
diff --git a/cscore/CMakeLists.txt b/cscore/CMakeLists.txt
index 98f6d7e..9ab9ca7 100644
--- a/cscore/CMakeLists.txt
+++ b/cscore/CMakeLists.txt
@@ -46,8 +46,8 @@
set (cscore_config_dir share/cscore)
endif()
-configure_file(cscore-config.cmake.in ${CMAKE_BINARY_DIR}/cscore-config.cmake )
-install(FILES ${CMAKE_BINARY_DIR}/cscore-config.cmake DESTINATION ${cscore_config_dir})
+configure_file(cscore-config.cmake.in ${WPILIB_BINARY_DIR}/cscore-config.cmake )
+install(FILES ${WPILIB_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")
@@ -79,7 +79,7 @@
find_package(Java REQUIRED)
find_package(JNI REQUIRED)
include(UseJava)
- set(CMAKE_JAVA_COMPILE_FLAGS "-Xlint:unchecked")
+ set(CMAKE_JAVA_COMPILE_FLAGS "-encoding" "UTF8" "-Xlint:unchecked")
#find java files, copy them locally
@@ -87,11 +87,11 @@
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_JAR_FILE NAMES opencv-${OpenCV_VERSION_MAJOR}${OpenCV_VERSION_MINOR}${OpenCV_VERSION_PATCH}.jar PATHS ${OPENCV_JAVA_INSTALL_DIR} ${OpenCV_INSTALL_PATH}/bin ${OpenCV_INSTALL_PATH}/share/java NO_DEFAULT_PATH)
find_file(OPENCV_JNI_FILE NAMES libopencv_java${OpenCV_VERSION_MAJOR}${OpenCV_VERSION_MINOR}${OpenCV_VERSION_PATCH}.so
libopencv_java${OpenCV_VERSION_MAJOR}${OpenCV_VERSION_MINOR}${OpenCV_VERSION_PATCH}.dylib
opencv_java${OpenCV_VERSION_MAJOR}${OpenCV_VERSION_MINOR}${OpenCV_VERSION_PATCH}.dll
- PATHS ${OPENCV_JAVA_INSTALL_DIR} ${OpenCV_INSTALL_PATH}/bin ${OpenCV_INSTALL_PATH}/bin/Release ${OpenCV_INSTALL_PATH}/bin/Debug ${OpenCV_INSTALL_PATH}/lib NO_DEFAULT_PATH)
+ PATHS ${OPENCV_JAVA_INSTALL_DIR} ${OpenCV_INSTALL_PATH}/bin ${OpenCV_INSTALL_PATH}/bin/Release ${OpenCV_INSTALL_PATH}/bin/Debug ${OpenCV_INSTALL_PATH}/lib ${OpenCV_INSTALL_PATH}/lib/jni NO_DEFAULT_PATH)
file(GLOB
cscore_jni_src src/main/native/cpp/jni/CameraServerJNI.cpp)
diff --git a/cscore/build.gradle b/cscore/build.gradle
index 90e5c20..cd03465 100644
--- a/cscore/build.gradle
+++ b/cscore/build.gradle
@@ -60,12 +60,12 @@
ext {
sharedCvConfigs = [cscore : [],
- cscoreBase: [],
- cscoreDev : [],
- cscoreTest: [],
- cscoreJNIShared: []]
+ cscoreBase: [],
+ cscoreDev : [],
+ cscoreTest: [],
+ cscoreJNIShared: []]
staticCvConfigs = [cscoreJNI: [],
- cscoreJNICvStatic: []]
+ cscoreJNICvStatic: []]
useJava = true
useCpp = true
cvStaticBuild = true
@@ -127,43 +127,57 @@
File examplesTree = file("$projectDir/examples")
examplesTree.list(new FilenameFilter() {
- @Override
- public boolean accept(File current, String name) {
- return new File(current, name).isDirectory();
- }
-}).each {
- sharedCvConfigs.put(it, [])
- examplesMap.put(it, [])
-}
+ @Override
+ public boolean accept(File current, String name) {
+ return new File(current, name).isDirectory();
+ }
+ }).each {
+ sharedCvConfigs.put(it, [])
+ examplesMap.put(it, [])
+ }
apply from: "${rootDir}/shared/opencv.gradle"
+Action<List<String>> symbolFilter = { symbols ->
+ symbols.removeIf({ !it.startsWith('CS_') })
+} as Action<List<String>>;
+
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']
+ 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_') })
- }
- x64SymbolFilter = { symbols ->
- symbols.removeIf({ !it.startsWith('CS_') })
- }
+ x86SymbolFilter = symbolFilter
+ x64SymbolFilter = symbolFilter
}
cscoreJNICvStatic {
- x86SymbolFilter = { symbols ->
- symbols.removeIf({ !it.startsWith('CS_') })
- }
- x64SymbolFilter = { symbols ->
- symbols.removeIf({ !it.startsWith('CS_') })
- }
+ x86SymbolFilter = symbolFilter
+ x64SymbolFilter = symbolFilter
}
}
diff --git a/cscore/cscore-config.cmake.in b/cscore/cscore-config.cmake.in
index da85e8b..33e0af3 100644
--- a/cscore/cscore-config.cmake.in
+++ b/cscore/cscore-config.cmake.in
@@ -3,4 +3,5 @@
@WPIUTIL_DEP_REPLACE@
find_dependency(OpenCV)
+@FILENAME_DEP_REPLACE@
include(${SELF_DIR}/cscore.cmake)
diff --git a/cscore/examples/enum_usb/enum_usb.cpp b/cscore/examples/enum_usb/enum_usb.cpp
index 866e2f1..e9c1225 100644
--- a/cscore/examples/enum_usb/enum_usb.cpp
+++ b/cscore/examples/enum_usb/enum_usb.cpp
@@ -1,84 +1,78 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2017-2018 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
-#include <wpi/SmallString.h>
-#include <wpi/raw_ostream.h>
+#include <cstdio>
+
+#include <fmt/format.h>
#include "cscore.h"
int main() {
CS_Status status = 0;
- wpi::SmallString<64> buf;
for (const auto& caminfo : cs::EnumerateUsbCameras(&status)) {
- wpi::outs() << caminfo.dev << ": " << caminfo.path << " (" << caminfo.name
- << ")\n";
+ fmt::print("{}: {} ({})\n", caminfo.dev, caminfo.path, caminfo.name);
if (!caminfo.otherPaths.empty()) {
- wpi::outs() << "Other device paths:\n";
- for (auto&& path : caminfo.otherPaths)
- wpi::outs() << " " << path << '\n';
+ std::puts("Other device paths:");
+ for (auto&& path : caminfo.otherPaths) {
+ fmt::print(" {}\n", path);
+ }
}
cs::UsbCamera camera{"usbcam", caminfo.dev};
- wpi::outs() << "Properties:\n";
+ std::puts("Properties:");
for (const auto& prop : camera.EnumerateProperties()) {
- wpi::outs() << " " << prop.GetName();
+ fmt::print(" {}", prop.GetName());
switch (prop.GetKind()) {
case cs::VideoProperty::kBoolean:
- wpi::outs() << " (bool): "
- << "value=" << prop.Get()
- << " default=" << prop.GetDefault();
+ fmt::print(" (bool): value={} default={}", prop.Get(),
+ prop.GetDefault());
break;
case cs::VideoProperty::kInteger:
- wpi::outs() << " (int): "
- << "value=" << prop.Get() << " min=" << prop.GetMin()
- << " max=" << prop.GetMax() << " step=" << prop.GetStep()
- << " default=" << prop.GetDefault();
+ fmt::print(" (int): value={} min={} max={} step={} default={}",
+ prop.Get(), prop.GetMin(), prop.GetMax(), prop.GetStep(),
+ prop.GetDefault());
break;
case cs::VideoProperty::kString:
- wpi::outs() << " (string): " << prop.GetString(buf);
+ fmt::print(" (string): {}", prop.GetString());
break;
case cs::VideoProperty::kEnum: {
- wpi::outs() << " (enum): "
- << "value=" << prop.Get();
+ fmt::print(" (enum): value={}", prop.Get());
auto choices = prop.GetChoices();
for (size_t i = 0; i < choices.size(); ++i) {
- if (choices[i].empty()) continue;
- wpi::outs() << "\n " << i << ": " << choices[i];
+ if (!choices[i].empty()) {
+ fmt::print("\n {}: {}", i, choices[i]);
+ }
}
break;
}
default:
break;
}
- wpi::outs() << '\n';
+ std::fputc('\n', stdout);
}
- wpi::outs() << "Video Modes:\n";
+ std::puts("Video Modes:");
for (const auto& mode : camera.EnumerateVideoModes()) {
- wpi::outs() << " PixelFormat:";
+ const char* pixelFormat;
switch (mode.pixelFormat) {
case cs::VideoMode::kMJPEG:
- wpi::outs() << "MJPEG";
+ pixelFormat = "MJPEG";
break;
case cs::VideoMode::kYUYV:
- wpi::outs() << "YUYV";
+ pixelFormat = "YUYV";
break;
case cs::VideoMode::kRGB565:
- wpi::outs() << "RGB565";
+ pixelFormat = "RGB565";
break;
default:
- wpi::outs() << "Unknown";
+ pixelFormat = "Unknown";
break;
}
- wpi::outs() << " Width:" << mode.width;
- wpi::outs() << " Height:" << mode.height;
- wpi::outs() << " FPS:" << mode.fps << '\n';
+ fmt::print(" PixelFormat:{} Width:{} Height:{} FPS:{}\n", pixelFormat,
+ mode.width, mode.height, mode.fps);
}
}
}
diff --git a/cscore/examples/httpcvstream/httpcvstream.cpp b/cscore/examples/httpcvstream/httpcvstream.cpp
index 90d61d5..38a00db 100644
--- a/cscore/examples/httpcvstream/httpcvstream.cpp
+++ b/cscore/examples/httpcvstream/httpcvstream.cpp
@@ -1,13 +1,10 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#include <cstdio>
-#include <iostream>
+#include <fmt/core.h>
#include <opencv2/core/core.hpp>
#include "cscore.h"
@@ -27,11 +24,11 @@
for (;;) {
uint64_t time = cvsink.GrabFrame(test);
if (time == 0) {
- std::cout << "error: " << cvsink.GetError() << std::endl;
+ fmt::print("error: {}\n", cvsink.GetError());
continue;
}
- std::cout << "got frame at time " << time << " size " << test.size()
- << std::endl;
+ fmt::print("got frame at time {} size ({}, {})\n", time, test.size().width,
+ test.size().height);
cv::flip(test, flip, 0);
cvsource.PutFrame(flip);
}
diff --git a/cscore/examples/settings/settings.cpp b/cscore/examples/settings/settings.cpp
index 5aa919f..40961b4 100644
--- a/cscore/examples/settings/settings.cpp
+++ b/cscore/examples/settings/settings.cpp
@@ -1,28 +1,29 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2017-2018 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#include <chrono>
+#include <cstdio>
#include <thread>
-#include <wpi/SmallString.h>
-#include <wpi/raw_ostream.h>
+#include <fmt/format.h>
+#include <wpi/StringExtras.h>
#include "cscore.h"
int main(int argc, char** argv) {
if (argc < 2) {
- wpi::errs() << "Usage: settings camera [prop val] ... -- [prop val]...\n";
- wpi::errs() << " Example: settings 1 brightness 30 raw_contrast 10\n";
+ std::fputs("Usage: settings camera [prop val] ... -- [prop val]...\n",
+ stderr);
+ std::fputs(" Example: settings 1 brightness 30 raw_contrast 10\n", stderr);
return 1;
}
int id;
- if (wpi::StringRef{argv[1]}.getAsInteger(10, id)) {
- wpi::errs() << "Expected number for camera\n";
+ if (auto v = wpi::parse_integer<int>(argv[1], 10)) {
+ id = v.value();
+ } else {
+ std::fputs("Expected number for camera\n", stderr);
return 2;
}
@@ -30,75 +31,75 @@
// Set prior to connect
int arg = 2;
- wpi::StringRef propName;
- for (; arg < argc && wpi::StringRef{argv[arg]} != "--"; ++arg) {
+ std::string_view propName;
+ for (; arg < argc && std::string_view{argv[arg]} != "--"; ++arg) {
if (propName.empty()) {
propName = argv[arg];
} else {
- wpi::StringRef propVal{argv[arg]};
- int intVal;
- if (propVal.getAsInteger(10, intVal))
+ std::string_view propVal{argv[arg]};
+ if (auto v = wpi::parse_integer<int>(propVal, 10)) {
+ camera.GetProperty(propName).Set(v.value());
+ } else {
camera.GetProperty(propName).SetString(propVal);
- else
- camera.GetProperty(propName).Set(intVal);
- propName = wpi::StringRef{};
+ }
+ propName = {};
}
}
- if (arg < argc && wpi::StringRef{argv[arg]} == "--") ++arg;
+ if (arg < argc && std::string_view{argv[arg]} == "--") {
+ ++arg;
+ }
// Wait to connect
- while (!camera.IsConnected())
+ while (!camera.IsConnected()) {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
+ }
// Set rest
- propName = wpi::StringRef{};
+ propName = {};
for (; arg < argc; ++arg) {
if (propName.empty()) {
propName = argv[arg];
} else {
- wpi::StringRef propVal{argv[arg]};
- int intVal;
- if (propVal.getAsInteger(10, intVal))
+ std::string_view propVal{argv[arg]};
+ if (auto v = wpi::parse_integer<int>(propVal, 10)) {
+ camera.GetProperty(propName).Set(v.value());
+ } else {
camera.GetProperty(propName).SetString(propVal);
- else
- camera.GetProperty(propName).Set(intVal);
- propName = wpi::StringRef{};
+ }
+ propName = {};
}
}
// Print settings
- wpi::SmallString<64> buf;
- wpi::outs() << "Properties:\n";
+ std::puts("Properties:");
for (const auto& prop : camera.EnumerateProperties()) {
- wpi::outs() << " " << prop.GetName();
+ fmt::print(" {}", prop.GetName());
switch (prop.GetKind()) {
case cs::VideoProperty::kBoolean:
- wpi::outs() << " (bool): "
- << "value=" << prop.Get()
- << " default=" << prop.GetDefault();
+ fmt::print(" (bool): value={} default={}", prop.Get(),
+ prop.GetDefault());
break;
case cs::VideoProperty::kInteger:
- wpi::outs() << " (int): "
- << "value=" << prop.Get() << " min=" << prop.GetMin()
- << " max=" << prop.GetMax() << " step=" << prop.GetStep()
- << " default=" << prop.GetDefault();
+ fmt::print(" (int): value={} min={} max={} step={} default={}",
+ prop.Get(), prop.GetMin(), prop.GetMax(), prop.GetStep(),
+ prop.GetDefault());
break;
case cs::VideoProperty::kString:
- wpi::outs() << " (string): " << prop.GetString(buf);
+ fmt::print(" (string): {}", prop.GetString());
break;
case cs::VideoProperty::kEnum: {
- wpi::outs() << " (enum): "
- << "value=" << prop.Get();
+ fmt::print(" (enum): value={}", prop.Get());
auto choices = prop.GetChoices();
for (size_t i = 0; i < choices.size(); ++i) {
- if (choices[i].empty()) continue;
- wpi::outs() << "\n " << i << ": " << choices[i];
+ if (!choices[i].empty()) {
+ fmt::print("\n {}: {}", i, choices[i]);
+ }
}
break;
}
default:
break;
}
- wpi::outs() << '\n';
+ std::fputc('\n', stdout);
}
}
diff --git a/cscore/examples/usbcvstream/usbcvstream.cpp b/cscore/examples/usbcvstream/usbcvstream.cpp
index 9a4ab06..3635221 100644
--- a/cscore/examples/usbcvstream/usbcvstream.cpp
+++ b/cscore/examples/usbcvstream/usbcvstream.cpp
@@ -1,13 +1,8 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
-#include <cstdio>
-#include <iostream>
-
+#include <fmt/core.h>
#include <opencv2/core/core.hpp>
#include "cscore.h"
@@ -29,11 +24,11 @@
for (;;) {
uint64_t time = cvsink.GrabFrame(test);
if (time == 0) {
- std::cout << "error: " << cvsink.GetError() << std::endl;
+ fmt::print("error: {}\n", cvsink.GetError());
continue;
}
- std::cout << "got frame at time " << time << " size " << test.size()
- << std::endl;
+ fmt::print("got frame at time {} size ({}, {})\n", time, test.size().width,
+ test.size().height);
cv::flip(test, flip, 0);
cvsource.PutFrame(flip);
}
diff --git a/cscore/examples/usbstream/usbstream.cpp b/cscore/examples/usbstream/usbstream.cpp
index 2f23151..7a57e8d 100644
--- a/cscore/examples/usbstream/usbstream.cpp
+++ b/cscore/examples/usbstream/usbstream.cpp
@@ -1,21 +1,19 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2017-2018 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#include <cstdio>
-#include <wpi/raw_ostream.h>
+#include <fmt/format.h>
#include "cscore.h"
int main() {
- wpi::outs() << "hostname: " << cs::GetHostname() << '\n';
- wpi::outs() << "IPv4 network addresses:\n";
- for (const auto& addr : cs::GetNetworkInterfaces())
- wpi::outs() << " " << addr << '\n';
+ fmt::print("hostname: {}\n", cs::GetHostname());
+ std::puts("IPv4 network addresses:");
+ for (const auto& addr : cs::GetNetworkInterfaces()) {
+ fmt::print(" {}\n", addr);
+ }
cs::UsbCamera camera{"usbcam", 0};
camera.SetVideoMode(cs::VideoMode::kMJPEG, 320, 240, 30);
cs::MjpegServer mjpegServer{"httpserver", 8081};
@@ -24,9 +22,8 @@
CS_Status status = 0;
cs::AddListener(
[&](const cs::RawEvent& event) {
- wpi::outs() << "FPS=" << camera.GetActualFPS()
- << " MBPS=" << (camera.GetActualDataRate() / 1000000.0)
- << '\n';
+ fmt::print("FPS={} MBPS={}\n", camera.GetActualFPS(),
+ (camera.GetActualDataRate() / 1000000.0));
},
cs::RawEvent::kTelemetryUpdated, false, &status);
cs::SetTelemetryPeriod(1.0);
diff --git a/cscore/examples/usbviewer/usbviewer.cpp b/cscore/examples/usbviewer/usbviewer.cpp
index 75f961a..5c2e7c9 100644
--- a/cscore/examples/usbviewer/usbviewer.cpp
+++ b/cscore/examples/usbviewer/usbviewer.cpp
@@ -1,20 +1,18 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2020 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#include <atomic>
#include <thread>
#include <vector>
+#include <fmt/format.h>
+
#define IMGUI_DEFINE_MATH_OPERATORS
#include <imgui.h>
#include <imgui_internal.h>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc.hpp>
-#include <wpi/raw_ostream.h>
#include <wpi/spinlock.h>
#include <wpigui.h>
@@ -41,7 +39,7 @@
// get frame from camera
uint64_t time = cvsink.GrabFrame(frame);
if (time == 0) {
- wpi::outs() << "error: " << cvsink.GetError() << '\n';
+ fmt::print("error: {}\n", cvsink.GetError());
continue;
}
@@ -53,7 +51,9 @@
} else {
{
std::scoped_lock lock(sharedFreeListMutex);
- for (auto mat : sharedFreeList) sourceFreeList.emplace_back(mat);
+ for (auto mat : sharedFreeList) {
+ sourceFreeList.emplace_back(mat);
+ }
sharedFreeList.clear();
}
if (!sourceFreeList.empty()) {
@@ -71,7 +71,9 @@
auto prev = latestFrame.exchange(out);
// put prev on free list
- if (prev) sourceFreeList.emplace_back(prev);
+ if (prev) {
+ sourceFreeList.emplace_back(prev);
+ }
}
});
diff --git a/cscore/java-examples/RawCVMatSink.java b/cscore/java-examples/RawCVMatSink.java
index d9557f7..c0acc28 100644
--- a/cscore/java-examples/RawCVMatSink.java
+++ b/cscore/java-examples/RawCVMatSink.java
@@ -1,19 +1,14 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this 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;
+import java.nio.ByteBuffer;
+import org.opencv.core.CvType;
+import org.opencv.core.Mat;
public class RawCVMatSink extends ImageSink {
RawFrame frame = new RawFrame();
@@ -27,26 +22,25 @@
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;
+ 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.
+ * 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)
*/
@@ -55,24 +49,21 @@
}
/**
- * 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.
+ * 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)
+ * @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.
+ * 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.
+ * @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);
@@ -83,12 +74,20 @@
return rv;
}
- if (frame.getDataByteBuffer() != origByteBuffer || width != frame.getWidth() || height != frame.getHeight() || pixelFormat != frame.getPixelFormat()) {
+ 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 =
+ new Mat(
+ frame.getHeight(),
+ frame.getWidth(),
+ getCVFormat(VideoMode.getPixelFormatFromInt(pixelFormat)),
+ origByteBuffer);
}
tmpMat.copyTo(image);
return rv;
diff --git a/cscore/java-examples/RawCVMatSource.java b/cscore/java-examples/RawCVMatSource.java
index 65bd7d2..e000ae3 100644
--- a/cscore/java-examples/RawCVMatSource.java
+++ b/cscore/java-examples/RawCVMatSource.java
@@ -1,15 +1,11 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
package edu.wpi.cscore;
-import org.opencv.core.Mat;
-
import edu.wpi.cscore.VideoMode.PixelFormat;
+import org.opencv.core.Mat;
public class RawCVMatSource extends ImageSource {
/**
@@ -19,11 +15,9 @@
* @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));
+ super(
+ CameraServerJNI.createRawSource(
+ name, mode.pixelFormat.getValue(), mode.width, mode.height, mode.fps));
}
/**
@@ -35,16 +29,17 @@
* @param height height
* @param fps fps
*/
- public RawCVMatSource(String name, VideoMode.PixelFormat pixelFormat, int width, int height, int 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.
+ * <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
*/
@@ -54,6 +49,12 @@
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);
+ CameraServerJNI.putRawSourceFrame(
+ m_handle,
+ image.dataAddr(),
+ image.width(),
+ image.height(),
+ imgType,
+ (int) image.total() * channels);
}
}
diff --git a/cscore/src/dev/java/edu/wpi/cscore/DevMain.java b/cscore/src/dev/java/edu/wpi/cscore/DevMain.java
deleted file mode 100644
index 51bfd26..0000000
--- a/cscore/src/dev/java/edu/wpi/cscore/DevMain.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
-
-package edu.wpi.cscore;
-
-import edu.wpi.first.wpiutil.RuntimeDetector;
-
-public final class DevMain {
- /**
- * Main method.
- */
- public static void main(String[] args) {
- System.out.println("Hello World!");
- System.out.println(RuntimeDetector.getPlatformPath());
- System.out.println(CameraServerJNI.getHostname());
- }
-
- private DevMain() {
- }
-}
diff --git a/cscore/src/dev/java/edu/wpi/first/cscore/DevMain.java b/cscore/src/dev/java/edu/wpi/first/cscore/DevMain.java
new file mode 100644
index 0000000..11652f6
--- /dev/null
+++ b/cscore/src/dev/java/edu/wpi/first/cscore/DevMain.java
@@ -0,0 +1,18 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+package edu.wpi.first.cscore;
+
+import edu.wpi.first.util.RuntimeDetector;
+
+public final class DevMain {
+ /** Main method. */
+ public static void main(String[] args) {
+ System.out.println("Hello World!");
+ System.out.println(RuntimeDetector.getPlatformPath());
+ System.out.println(CameraServerJNI.getHostname());
+ }
+
+ private DevMain() {}
+}
diff --git a/cscore/src/dev/native/cpp/main.cpp b/cscore/src/dev/native/cpp/main.cpp
index f27f61f..279d72a 100644
--- a/cscore/src/dev/native/cpp/main.cpp
+++ b/cscore/src/dev/native/cpp/main.cpp
@@ -1,12 +1,11 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
-#include <iostream>
+#include <fmt/core.h>
#include "cscore.h"
-int main() { std::cout << cs::GetHostname() << std::endl; }
+int main() {
+ fmt::print("{}\n", cs::GetHostname());
+}
diff --git a/cscore/src/main/java/edu/wpi/cscore/CvSink.java b/cscore/src/main/java/edu/wpi/cscore/CvSink.java
deleted file mode 100644
index f12dcc7..0000000
--- a/cscore/src/main/java/edu/wpi/cscore/CvSink.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
-
-package edu.wpi.cscore;
-
-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 ImageSink {
- /**
- * 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 CvSink(String name) {
- super(CameraServerCvJNI.createCvSink(name));
- }
-
- /// Create a sink for accepting OpenCV images in a separate thread.
- /// 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().
- //public CvSink(wpi::StringRef name,
- // std::function<void(uint64_t time)> processFrame) {
- // super(CameraServerJNI.createCvSinkCallback(name, processFrame));
- //}
-
- /**
- * 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) {
- return CameraServerCvJNI.grabSinkFrameTimeout(m_handle, image.nativeObj, timeout);
- }
-
- /**
- * Wait for the next frame and get the image. May block forever.
- * 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 grabFrameNoTimeout(Mat image) {
- return CameraServerCvJNI.grabSinkFrame(m_handle, image.nativeObj);
- }
-}
diff --git a/cscore/src/main/java/edu/wpi/cscore/CvSource.java b/cscore/src/main/java/edu/wpi/cscore/CvSource.java
deleted file mode 100644
index c04d197..0000000
--- a/cscore/src/main/java/edu/wpi/cscore/CvSource.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
-
-package edu.wpi.cscore;
-
-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 ImageSource {
- /**
- * Create an OpenCV source.
- *
- * @param name Source name (arbitrary unique identifier)
- * @param mode Video mode being generated
- */
- public CvSource(String name, VideoMode mode) {
- super(CameraServerCvJNI.createCvSource(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 CvSource(String name, VideoMode.PixelFormat pixelFormat, int width, int height, int fps) {
- super(CameraServerCvJNI.createCvSource(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) {
- CameraServerCvJNI.putSourceFrame(m_handle, image.nativeObj);
- }
-
-}
diff --git a/cscore/src/main/java/edu/wpi/cscore/ImageSink.java b/cscore/src/main/java/edu/wpi/cscore/ImageSink.java
deleted file mode 100644
index f755fb6..0000000
--- a/cscore/src/main/java/edu/wpi/cscore/ImageSink.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*----------------------------------------------------------------------------*/
-/* 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);
- }
-}
diff --git a/cscore/src/main/java/edu/wpi/cscore/ImageSource.java b/cscore/src/main/java/edu/wpi/cscore/ImageSource.java
deleted file mode 100644
index 3787516..0000000
--- a/cscore/src/main/java/edu/wpi/cscore/ImageSource.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*----------------------------------------------------------------------------*/
-/* 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);
- }
-}
diff --git a/cscore/src/main/java/edu/wpi/cscore/UsbCameraInfo.java b/cscore/src/main/java/edu/wpi/cscore/UsbCameraInfo.java
deleted file mode 100644
index c3a8309..0000000
--- a/cscore/src/main/java/edu/wpi/cscore/UsbCameraInfo.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
-
-package edu.wpi.cscore;
-
-/**
- * USB camera information.
- */
-public class UsbCameraInfo {
- /**
- * Create a new set of UsbCameraInfo.
- *
- * @param dev Device number (e.g. N in '/dev/videoN' on Linux)
- * @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, int vendorId,
- int productId) {
- this.dev = dev;
- this.path = path;
- this.name = name;
- this.otherPaths = otherPaths;
- this.vendorId = vendorId;
- this.productId = productId;
- }
-
- /**
- * Device number (e.g. N in '/dev/videoN' on Linux).
- */
- @SuppressWarnings("MemberName")
- public int dev;
-
- /**
- * Path to device if available (e.g. '/dev/video0' on Linux).
- */
- @SuppressWarnings("MemberName")
- public String path;
-
- /**
- * Vendor/model name of the camera as provided by the USB driver.
- */
- @SuppressWarnings("MemberName")
- public String name;
-
- /**
- * Other path aliases to device (e.g. '/dev/v4l/by-id/...' etc on Linux).
- */
- @SuppressWarnings("MemberName")
- public String[] otherPaths;
-
- /**
- * USB vendor id.
- */
- @SuppressWarnings("MemberName")
- public int vendorId;
-
- /**
- * USB product id.
- */
- @SuppressWarnings("MemberName")
- public int productId;
-}
diff --git a/cscore/src/main/java/edu/wpi/cscore/VideoEvent.java b/cscore/src/main/java/edu/wpi/cscore/VideoEvent.java
deleted file mode 100644
index 7f4599d..0000000
--- a/cscore/src/main/java/edu/wpi/cscore/VideoEvent.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2018 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;
-
-/**
- * Video event.
- */
-public class VideoEvent {
- public enum Kind {
- kUnknown(0x0000),
- kSourceCreated(0x0001),
- kSourceDestroyed(0x0002),
- kSourceConnected(0x0004),
- kSourceDisconnected(0x0008),
- kSourceVideoModesUpdated(0x0010),
- kSourceVideoModeChanged(0x0020),
- kSourcePropertyCreated(0x0040),
- kSourcePropertyValueUpdated(0x0080),
- kSourcePropertyChoicesUpdated(0x0100),
- kSinkSourceChanged(0x0200),
- kSinkCreated(0x0400),
- kSinkDestroyed(0x0800),
- kSinkEnabled(0x1000),
- kSinkDisabled(0x2000),
- kNetworkInterfacesChanged(0x4000),
- kTelemetryUpdated(0x8000),
- kSinkPropertyCreated(0x10000),
- kSinkPropertyValueUpdated(0x20000),
- kSinkPropertyChoicesUpdated(0x40000);
-
- @SuppressWarnings("MemberName")
- private final int value;
-
- Kind(int value) {
- this.value = value;
- }
-
- public int getValue() {
- return value;
- }
- }
-
- /**
- * Convert from the numerical representation of kind to an enum type.
- *
- * @param kind The numerical representation of kind
- * @return The kind
- */
- @SuppressWarnings("PMD.CyclomaticComplexity")
- public static Kind getKindFromInt(int kind) {
- switch (kind) {
- case 0x0001: return Kind.kSourceCreated;
- case 0x0002: return Kind.kSourceDestroyed;
- case 0x0004: return Kind.kSourceConnected;
- case 0x0008: return Kind.kSourceDisconnected;
- case 0x0010: return Kind.kSourceVideoModesUpdated;
- case 0x0020: return Kind.kSourceVideoModeChanged;
- case 0x0040: return Kind.kSourcePropertyCreated;
- case 0x0080: return Kind.kSourcePropertyValueUpdated;
- case 0x0100: return Kind.kSourcePropertyChoicesUpdated;
- case 0x0200: return Kind.kSinkSourceChanged;
- case 0x0400: return Kind.kSinkCreated;
- case 0x0800: return Kind.kSinkDestroyed;
- case 0x1000: return Kind.kSinkEnabled;
- case 0x2000: return Kind.kSinkDisabled;
- case 0x4000: return Kind.kNetworkInterfacesChanged;
- case 0x10000: return Kind.kSinkPropertyCreated;
- case 0x20000: return Kind.kSinkPropertyValueUpdated;
- case 0x40000: return Kind.kSinkPropertyChoicesUpdated;
- default: return Kind.kUnknown;
- }
- }
-
- @SuppressWarnings("PMD.ExcessiveParameterList")
- VideoEvent(int kind, int source, int sink, String name, int pixelFormat,
- int width, int height, int fps, int property, int propertyKind,
- int value, String valueStr) {
- this.kind = getKindFromInt(kind);
- this.sourceHandle = source;
- this.sinkHandle = sink;
- this.name = name;
- this.mode = new VideoMode(pixelFormat, width, height, fps);
- this.propertyHandle = property;
- this.propertyKind = VideoProperty.getKindFromInt(propertyKind);
- this.value = value;
- this.valueStr = valueStr;
- }
-
- @SuppressWarnings("MemberName")
- public Kind kind;
-
- // Valid for kSource* and kSink* respectively
- @SuppressWarnings("MemberName")
- public int sourceHandle;
- @SuppressWarnings("MemberName")
- public int sinkHandle;
-
- // Source/sink/property name
- @SuppressWarnings("MemberName")
- public String name;
-
- // Fields for kSourceVideoModeChanged event
- @SuppressWarnings("MemberName")
- public VideoMode mode;
-
- // Fields for kSourceProperty* events
- @SuppressWarnings("MemberName")
- public int propertyHandle;
- @SuppressWarnings("MemberName")
- public VideoProperty.Kind propertyKind;
- @SuppressWarnings("MemberName")
- public int value;
- @SuppressWarnings("MemberName")
- public String valueStr;
-
- public VideoSource getSource() {
- return new VideoSource(CameraServerJNI.copySource(sourceHandle));
- }
-
- public VideoSink getSink() {
- return new VideoSink(CameraServerJNI.copySink(sinkHandle));
- }
-
- public VideoProperty getProperty() {
- return new VideoProperty(propertyHandle, propertyKind);
- }
-
-}
diff --git a/cscore/src/main/java/edu/wpi/cscore/VideoException.java b/cscore/src/main/java/edu/wpi/cscore/VideoException.java
deleted file mode 100644
index 8c35517..0000000
--- a/cscore/src/main/java/edu/wpi/cscore/VideoException.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2018 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;
-
-/**
- * An exception raised by the camera server.
- */
-public class VideoException extends RuntimeException {
- private static final long serialVersionUID = -9155939328084105145L;
-
- public VideoException(String msg) {
- super(msg);
- }
-
- @Override
- public String toString() {
- return "VideoException [" + super.toString() + "]";
- }
-}
diff --git a/cscore/src/main/java/edu/wpi/cscore/VideoListener.java b/cscore/src/main/java/edu/wpi/cscore/VideoListener.java
deleted file mode 100644
index 2a35505..0000000
--- a/cscore/src/main/java/edu/wpi/cscore/VideoListener.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
-
-package edu.wpi.cscore;
-
-import java.util.function.Consumer;
-
-/**
- * An event listener. This calls back to a desigated callback function when
- * an event matching the specified mask is generated by the library.
- */
-public class VideoListener implements AutoCloseable {
- /**
- * Create an event listener.
- *
- * @param listener Listener function
- * @param eventMask Bitmask of VideoEvent.Type values
- * @param immediateNotify Whether callback should be immediately called with
- * a representative set of events for the current library state.
- */
- public VideoListener(Consumer<VideoEvent> listener, int eventMask,
- boolean immediateNotify) {
- m_handle = CameraServerJNI.addListener(listener, eventMask, immediateNotify);
- }
-
- @Override
- public synchronized void close() {
- if (m_handle != 0) {
- CameraServerJNI.removeListener(m_handle);
- }
- m_handle = 0;
- }
-
- public boolean isValid() {
- return m_handle != 0;
- }
-
- private int m_handle;
-}
diff --git a/cscore/src/main/java/edu/wpi/cscore/VideoMode.java b/cscore/src/main/java/edu/wpi/cscore/VideoMode.java
deleted file mode 100644
index dec4686..0000000
--- a/cscore/src/main/java/edu/wpi/cscore/VideoMode.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2018 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;
-
-/**
- * Video mode.
- */
-public class VideoMode {
- public enum PixelFormat {
- kUnknown(0), kMJPEG(1), kYUYV(2), kRGB565(3), kBGR(4), kGray(5);
-
- @SuppressWarnings("MemberName")
- private final int value;
-
- PixelFormat(int value) {
- this.value = value;
- }
-
- public int getValue() {
- return value;
- }
- }
-
- private static final PixelFormat[] m_pixelFormatValues = PixelFormat.values();
-
- public static PixelFormat getPixelFormatFromInt(int pixelFormat) {
- return m_pixelFormatValues[pixelFormat];
- }
-
- /**
- * Create a new video mode.
- */
- public VideoMode(int pixelFormat, int width, int height, int fps) {
- this.pixelFormat = getPixelFormatFromInt(pixelFormat);
- this.width = width;
- this.height = height;
- this.fps = fps;
- }
-
- /**
- * Create a new video mode.
- */
- public VideoMode(PixelFormat pixelFormat, int width, int height, int fps) {
- this.pixelFormat = pixelFormat;
- this.width = width;
- this.height = height;
- this.fps = fps;
- }
-
- /**
- * Pixel format.
- */
- @SuppressWarnings("MemberName")
- public PixelFormat pixelFormat;
-
- /**
- * Width in pixels.
- */
- @SuppressWarnings("MemberName")
- public int width;
-
- /**
- * Height in pixels.
- */
- @SuppressWarnings("MemberName")
- public int height;
-
- /**
- * Frames per second.
- */
- @SuppressWarnings("MemberName")
- public int fps;
-}
diff --git a/cscore/src/main/java/edu/wpi/cscore/raw/RawFrame.java b/cscore/src/main/java/edu/wpi/cscore/raw/RawFrame.java
deleted file mode 100644
index 0e7a9ce..0000000
--- a/cscore/src/main/java/edu/wpi/cscore/raw/RawFrame.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*----------------------------------------------------------------------------*/
-/* 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;
- }
-}
diff --git a/cscore/src/main/java/edu/wpi/cscore/raw/RawSink.java b/cscore/src/main/java/edu/wpi/cscore/raw/RawSink.java
deleted file mode 100644
index 535f356..0000000
--- a/cscore/src/main/java/edu/wpi/cscore/raw/RawSink.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*----------------------------------------------------------------------------*/
-/* 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);
- }
-}
diff --git a/cscore/src/main/java/edu/wpi/cscore/raw/RawSource.java b/cscore/src/main/java/edu/wpi/cscore/raw/RawSource.java
deleted file mode 100644
index 9dfb3f3..0000000
--- a/cscore/src/main/java/edu/wpi/cscore/raw/RawSource.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*----------------------------------------------------------------------------*/
-/* 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);
- }
-}
diff --git a/cscore/src/main/java/edu/wpi/cscore/AxisCamera.java b/cscore/src/main/java/edu/wpi/first/cscore/AxisCamera.java
similarity index 62%
rename from cscore/src/main/java/edu/wpi/cscore/AxisCamera.java
rename to cscore/src/main/java/edu/wpi/first/cscore/AxisCamera.java
index 8eef0b3..296bd6b 100644
--- a/cscore/src/main/java/edu/wpi/cscore/AxisCamera.java
+++ b/cscore/src/main/java/edu/wpi/first/cscore/AxisCamera.java
@@ -1,15 +1,10 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2018 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
-package edu.wpi.cscore;
+package edu.wpi.first.cscore;
-/**
- * A source that represents an Axis IP camera.
- */
+/** A source that represents an Axis IP camera. */
public class AxisCamera extends HttpCamera {
private static String hostToUrl(String host) {
return "http://" + host + "/mjpg/video.mjpg";
diff --git a/cscore/src/main/java/edu/wpi/cscore/CameraServerCvJNI.java b/cscore/src/main/java/edu/wpi/first/cscore/CameraServerCvJNI.java
similarity index 61%
rename from cscore/src/main/java/edu/wpi/cscore/CameraServerCvJNI.java
rename to cscore/src/main/java/edu/wpi/first/cscore/CameraServerCvJNI.java
index 78b4ff8..3527dae 100644
--- a/cscore/src/main/java/edu/wpi/cscore/CameraServerCvJNI.java
+++ b/cscore/src/main/java/edu/wpi/first/cscore/CameraServerCvJNI.java
@@ -1,19 +1,14 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
-package edu.wpi.cscore;
+package edu.wpi.first.cscore;
+import edu.wpi.first.util.RuntimeLoader;
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;
@@ -36,7 +31,8 @@
if (Helper.getExtractOnStaticLoad()) {
try {
CameraServerJNI.forceLoad();
- loader = new RuntimeLoader<>(opencvName, RuntimeLoader.getDefaultExtractionRoot(), Core.class);
+ loader =
+ new RuntimeLoader<>(opencvName, RuntimeLoader.getDefaultExtractionRoot(), Core.class);
loader.loadLibraryHashed();
} catch (IOException ex) {
ex.printStackTrace();
@@ -48,25 +44,31 @@
/**
* Force load the library.
+ *
+ * @throws IOException if library load failed
*/
public static synchronized void forceLoad() throws IOException {
if (libraryLoaded) {
return;
}
CameraServerJNI.forceLoad();
- loader = new RuntimeLoader<>(Core.NATIVE_LIBRARY_NAME, RuntimeLoader.getDefaultExtractionRoot(), Core.class);
+ 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 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,
+ // 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);
}
diff --git a/cscore/src/main/java/edu/wpi/cscore/CameraServerJNI.java b/cscore/src/main/java/edu/wpi/first/cscore/CameraServerJNI.java
similarity index 71%
rename from cscore/src/main/java/edu/wpi/cscore/CameraServerJNI.java
rename to cscore/src/main/java/edu/wpi/first/cscore/CameraServerJNI.java
index b8a548c..fe46baf 100644
--- a/cscore/src/main/java/edu/wpi/cscore/CameraServerJNI.java
+++ b/cscore/src/main/java/edu/wpi/first/cscore/CameraServerJNI.java
@@ -1,20 +1,16 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2020 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
-package edu.wpi.cscore;
+package edu.wpi.first.cscore;
+import edu.wpi.first.cscore.raw.RawFrame;
+import edu.wpi.first.util.RuntimeLoader;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
-import edu.wpi.cscore.raw.RawFrame;
-import edu.wpi.first.wpiutil.RuntimeLoader;
-
public class CameraServerJNI {
static boolean libraryLoaded = false;
@@ -35,7 +31,9 @@
static {
if (Helper.getExtractOnStaticLoad()) {
try {
- loader = new RuntimeLoader<>("cscorejni", RuntimeLoader.getDefaultExtractionRoot(), CameraServerJNI.class);
+ loader =
+ new RuntimeLoader<>(
+ "cscorejni", RuntimeLoader.getDefaultExtractionRoot(), CameraServerJNI.class);
loader.loadLibrary();
} catch (IOException ex) {
ex.printStackTrace();
@@ -47,12 +45,16 @@
/**
* Force load the library.
+ *
+ * @throws IOException if library load failed
*/
public static synchronized void forceLoad() throws IOException {
if (libraryLoaded) {
return;
}
- loader = new RuntimeLoader<>("cscorejni", RuntimeLoader.getDefaultExtractionRoot(), CameraServerJNI.class);
+ loader =
+ new RuntimeLoader<>(
+ "cscorejni", RuntimeLoader.getDefaultExtractionRoot(), CameraServerJNI.class);
loader.loadLibrary();
libraryLoaded = true;
}
@@ -61,89 +63,159 @@
// Property Functions
//
public static native int getPropertyKind(int property);
+
public static native String getPropertyName(int property);
+
public static native int getProperty(int property);
+
public static native void setProperty(int property, int value);
+
public static native int getPropertyMin(int property);
+
public static native int getPropertyMax(int property);
+
public static native int getPropertyStep(int property);
+
public static native int getPropertyDefault(int property);
+
public static native String getStringProperty(int property);
+
public static native void setStringProperty(int property, String value);
+
public static native String[] getEnumPropertyChoices(int property);
//
// Source Creation Functions
//
public static native int createUsbCameraDev(String name, int dev);
+
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 createRawSource(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
//
public static native int getSourceKind(int source);
+
public static native String getSourceName(int source);
+
public static native String getSourceDescription(int source);
+
public static native long getSourceLastFrameTime(int source);
+
public static native void setSourceConnectionStrategy(int source, int strategy);
+
public static native boolean isSourceConnected(int source);
+
public static native boolean isSourceEnabled(int source);
+
public static native int getSourceProperty(int source, String name);
+
public static native int[] enumerateSourceProperties(int source);
+
public static native VideoMode getSourceVideoMode(int source);
- public static native boolean setSourceVideoMode(int source, int pixelFormat, int width, int height, int fps);
+
+ public static native boolean setSourceVideoMode(
+ int source, int pixelFormat, int width, int height, int fps);
+
public static native boolean setSourcePixelFormat(int source, int pixelFormat);
+
public static native boolean setSourceResolution(int source, int width, int height);
+
public static native boolean setSourceFPS(int source, int fps);
+
public static native boolean setSourceConfigJson(int source, String config);
+
public static native String getSourceConfigJson(int source);
+
public static native VideoMode[] enumerateSourceVideoModes(int source);
+
public static native int[] enumerateSourceSinks(int source);
+
public static native int copySource(int source);
+
public static native void releaseSource(int source);
//
// Camera Source Common Property Fuctions
//
public static native void setCameraBrightness(int source, int brightness);
+
public static native int getCameraBrightness(int source);
+
public static native void setCameraWhiteBalanceAuto(int source);
+
public static native void setCameraWhiteBalanceHoldCurrent(int source);
+
public static native void setCameraWhiteBalanceManual(int source, int value);
+
public static native void setCameraExposureAuto(int source);
+
public static native void setCameraExposureHoldCurrent(int source);
+
public static native void setCameraExposureManual(int source, int value);
//
// UsbCamera Source Functions
//
public static native void setUsbCameraPath(int source, String path);
+
public static native String getUsbCameraPath(int source);
+
public static native UsbCameraInfo getUsbCameraInfo(int source);
//
// HttpCamera Source Functions
//
public static native int getHttpCameraKind(int source);
+
public static native void setHttpCameraUrls(int source, String[] urls);
+
public static native String[] getHttpCameraUrls(int source);
//
// Image Source Functions
//
- 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 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());
+ 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);
- public static native int createSourceProperty(int source, String name, int kind, int minimum, int maximum, int step, int defaultValue, int value);
- public static native void setSourceEnumPropertyChoices(int source, int property, String[] choices);
+
+ public static native int createSourceProperty(
+ int source,
+ String name,
+ int kind,
+ int minimum,
+ int maximum,
+ int step,
+ int defaultValue,
+ int value);
+
+ public static native void setSourceEnumPropertyChoices(
+ int source, int property, String[] choices);
//
// Sink Creation Functions
@@ -156,22 +228,34 @@
// Sink Functions
//
public static native int getSinkKind(int sink);
+
public static native String getSinkName(int sink);
+
public static native String getSinkDescription(int sink);
+
public static native int getSinkProperty(int sink, String name);
+
public static native int[] enumerateSinkProperties(int sink);
+
public static native boolean setSinkConfigJson(int sink, String config);
+
public static native String getSinkConfigJson(int sink);
+
public static native void setSinkSource(int sink, int source);
+
public static native int getSinkSourceProperty(int sink, String name);
+
public static native int getSinkSource(int sink);
+
public static native int copySink(int sink);
+
public static native void releaseSink(int sink);
//
// MjpegServer Sink Functions
//
public static native String getMjpegServerListenAddress(int sink);
+
public static native int getMjpegServerPort(int sink);
//
@@ -179,26 +263,73 @@
//
public static native void setSinkDescription(int sink, String description);
- 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);
+ 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());
+ 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);
+ 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);
//
// Listener Functions
//
- public static native int addListener(Consumer<VideoEvent> listener,
- int eventMask, boolean immediateNotify);
+ public static native int addListener(
+ Consumer<VideoEvent> listener, int eventMask, boolean immediateNotify);
public static native void removeListener(int handle);
+ public static native int createListenerPoller();
+
+ public static native void destroyListenerPoller(int poller);
+
+ public static native int addPolledListener(int poller, int eventMask, boolean immediateNotify);
+
+ public static native VideoEvent[] pollListener(int poller) throws InterruptedException;
+
+ public static native VideoEvent[] pollListenerTimeout(int poller, double timeout)
+ throws InterruptedException;
+
+ public static native void cancelPollListener(int poller);
+
//
// Telemetry Functions
//
@@ -206,7 +337,6 @@
kSourceBytesReceived(1),
kSourceFramesReceived(2);
- @SuppressWarnings("MemberName")
private final int value;
TelemetryKind(int value) {
@@ -217,13 +347,19 @@
return value;
}
}
+
public static native void setTelemetryPeriod(double seconds);
+
public static native double getTelemetryElapsedTime();
+
public static native long getTelemetryValue(int handle, int kind);
+
public static long getTelemetryValue(int handle, TelemetryKind kind) {
return getTelemetryValue(handle, kind.getValue());
}
+
public static native double getTelemetryAverageValue(int handle, int kind);
+
public static double getTelemetryAverageValue(int handle, TelemetryKind kind) {
return getTelemetryAverageValue(handle, kind.getValue());
}
@@ -235,6 +371,7 @@
public interface LoggerFunction {
void apply(int level, String file, int line, String msg);
}
+
public static native void setLogger(LoggerFunction func, int minLevel);
//
diff --git a/cscore/src/main/java/edu/wpi/first/cscore/CvSink.java b/cscore/src/main/java/edu/wpi/first/cscore/CvSink.java
new file mode 100644
index 0000000..88ca8b1
--- /dev/null
+++ b/cscore/src/main/java/edu/wpi/first/cscore/CvSink.java
@@ -0,0 +1,72 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+package edu.wpi.first.cscore;
+
+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 ImageSink {
+ /**
+ * 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 CvSink(String name) {
+ super(CameraServerCvJNI.createCvSink(name));
+ }
+
+ /// Create a sink for accepting OpenCV images in a separate thread.
+ /// 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().
+ // public CvSink(wpi::StringRef name,
+ // std::function<void(uint64_t time)> processFrame) {
+ // super(CameraServerJNI.createCvSinkCallback(name, processFrame));
+ // }
+
+ /**
+ * 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.
+ *
+ * @param image Where to store the image.
+ * @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.
+ *
+ * @param image Where to store the image.
+ * @param timeout Retrieval timeout in seconds.
+ * @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) {
+ return CameraServerCvJNI.grabSinkFrameTimeout(m_handle, image.nativeObj, timeout);
+ }
+
+ /**
+ * Wait for the next frame and get the image. May block forever. The provided image will have
+ * three 3-bit channels stored in BGR order.
+ *
+ * @param image Where to store the image.
+ * @return Frame time, or 0 on error (call GetError() to obtain the error message); the frame time
+ * is in 1 us increments.
+ */
+ public long grabFrameNoTimeout(Mat image) {
+ return CameraServerCvJNI.grabSinkFrame(m_handle, image.nativeObj);
+ }
+}
diff --git a/cscore/src/main/java/edu/wpi/first/cscore/CvSource.java b/cscore/src/main/java/edu/wpi/first/cscore/CvSource.java
new file mode 100644
index 0000000..3934a09
--- /dev/null
+++ b/cscore/src/main/java/edu/wpi/first/cscore/CvSource.java
@@ -0,0 +1,51 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+package edu.wpi.first.cscore;
+
+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 ImageSource {
+ /**
+ * Create an OpenCV source.
+ *
+ * @param name Source name (arbitrary unique identifier)
+ * @param mode Video mode being generated
+ */
+ public CvSource(String name, VideoMode mode) {
+ super(
+ CameraServerCvJNI.createCvSource(
+ 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 CvSource(String name, VideoMode.PixelFormat pixelFormat, int width, int height, int fps) {
+ super(CameraServerCvJNI.createCvSource(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) {
+ CameraServerCvJNI.putSourceFrame(m_handle, image.nativeObj);
+ }
+}
diff --git a/cscore/src/main/java/edu/wpi/cscore/HttpCamera.java b/cscore/src/main/java/edu/wpi/first/cscore/HttpCamera.java
similarity index 73%
rename from cscore/src/main/java/edu/wpi/cscore/HttpCamera.java
rename to cscore/src/main/java/edu/wpi/first/cscore/HttpCamera.java
index 533d00f..8c72350 100644
--- a/cscore/src/main/java/edu/wpi/cscore/HttpCamera.java
+++ b/cscore/src/main/java/edu/wpi/first/cscore/HttpCamera.java
@@ -1,20 +1,17 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2018 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
-package edu.wpi.cscore;
+package edu.wpi.first.cscore;
-/**
- * A source that represents a MJPEG-over-HTTP (IP) camera.
- */
+/** A source that represents a MJPEG-over-HTTP (IP) camera. */
public class HttpCamera extends VideoCamera {
public enum HttpCameraKind {
- kUnknown(0), kMJPGStreamer(1), kCSCore(2), kAxis(3);
+ kUnknown(0),
+ kMJPGStreamer(1),
+ kCSCore(2),
+ kAxis(3);
- @SuppressWarnings("MemberName")
private final int value;
HttpCameraKind(int value) {
@@ -34,10 +31,14 @@
*/
public static HttpCameraKind getHttpCameraKindFromInt(int kind) {
switch (kind) {
- case 1: return HttpCameraKind.kMJPGStreamer;
- case 2: return HttpCameraKind.kCSCore;
- case 3: return HttpCameraKind.kAxis;
- default: return HttpCameraKind.kUnknown;
+ case 1:
+ return HttpCameraKind.kMJPGStreamer;
+ case 2:
+ return HttpCameraKind.kCSCore;
+ case 3:
+ return HttpCameraKind.kAxis;
+ default:
+ return HttpCameraKind.kUnknown;
}
}
@@ -86,8 +87,9 @@
/**
* Get the kind of HTTP camera.
*
- * <p>Autodetection can result in returning a different value than the camera
- * was created with.
+ * <p>Autodetection can result in returning a different value than the camera was created with.
+ *
+ * @return The kind of HTTP camera.
*/
public HttpCameraKind getHttpCameraKind() {
return getHttpCameraKindFromInt(CameraServerJNI.getHttpCameraKind(m_handle));
@@ -95,6 +97,8 @@
/**
* Change the URLs used to connect to the camera.
+ *
+ * @param urls Array of Camera URLs
*/
public void setUrls(String[] urls) {
CameraServerJNI.setHttpCameraUrls(m_handle, urls);
@@ -102,6 +106,8 @@
/**
* Get the URLs used to connect to the camera.
+ *
+ * @return Array of camera URLs.
*/
public String[] getUrls() {
return CameraServerJNI.getHttpCameraUrls(m_handle);
diff --git a/cscore/src/main/java/edu/wpi/first/cscore/ImageSink.java b/cscore/src/main/java/edu/wpi/first/cscore/ImageSink.java
new file mode 100644
index 0000000..1c4cac2
--- /dev/null
+++ b/cscore/src/main/java/edu/wpi/first/cscore/ImageSink.java
@@ -0,0 +1,40 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+package edu.wpi.first.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.
+ *
+ * @return Error string.
+ */
+ 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.
+ *
+ * @param enabled Enable to get new frames.
+ */
+ public void setEnabled(boolean enabled) {
+ CameraServerJNI.setSinkEnabled(m_handle, enabled);
+ }
+}
diff --git a/cscore/src/main/java/edu/wpi/first/cscore/ImageSource.java b/cscore/src/main/java/edu/wpi/first/cscore/ImageSource.java
new file mode 100644
index 0000000..6bebed8
--- /dev/null
+++ b/cscore/src/main/java/edu/wpi/first/cscore/ImageSource.java
@@ -0,0 +1,136 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+package edu.wpi.first.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.
+ *
+ * @param msg Error message.
+ */
+ 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);
+ }
+}
diff --git a/cscore/src/main/java/edu/wpi/cscore/MjpegServer.java b/cscore/src/main/java/edu/wpi/first/cscore/MjpegServer.java
similarity index 63%
rename from cscore/src/main/java/edu/wpi/cscore/MjpegServer.java
rename to cscore/src/main/java/edu/wpi/first/cscore/MjpegServer.java
index 4c00aed..54c8053 100644
--- a/cscore/src/main/java/edu/wpi/cscore/MjpegServer.java
+++ b/cscore/src/main/java/edu/wpi/first/cscore/MjpegServer.java
@@ -1,15 +1,10 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
-package edu.wpi.cscore;
+package edu.wpi.first.cscore;
-/**
- * A sink that acts as a MJPEG-over-HTTP network server.
- */
+/** A sink that acts as a MJPEG-over-HTTP network server. */
public class MjpegServer extends VideoSink {
/**
* Create a MJPEG-over-HTTP server sink.
@@ -34,6 +29,8 @@
/**
* Get the listen address of the server.
+ *
+ * @return The listen address.
*/
public String getListenAddress() {
return CameraServerJNI.getMjpegServerListenAddress(m_handle);
@@ -41,6 +38,8 @@
/**
* Get the port number of the server.
+ *
+ * @return The port number.
*/
public int getPort() {
return CameraServerJNI.getMjpegServerPort(m_handle);
@@ -49,13 +48,11 @@
/**
* Set the stream resolution for clients that don't specify it.
*
- * <p>It is not necessary to set this if it is the same as the source
- * resolution.
+ * <p>It is not necessary to set this if it is the same as the source resolution.
*
- * <p>Setting this different than the source resolution will result in
- * increased CPU usage, particularly for MJPEG source cameras, as it will
- * decompress, resize, and recompress the image, instead of using the
- * camera's MJPEG image directly.
+ * <p>Setting this different than the source resolution will result in increased CPU usage,
+ * particularly for MJPEG source cameras, as it will decompress, resize, and recompress the image,
+ * instead of using the camera's MJPEG image directly.
*
* @param width width, 0 for unspecified
* @param height height, 0 for unspecified
@@ -79,26 +76,24 @@
/**
* Set the compression for clients that don't specify it.
*
- * <p>Setting this will result in increased CPU usage for MJPEG source cameras
- * as it will decompress and recompress the image instead of using the
- * camera's MJPEG image directly.
+ * <p>Setting this will result in increased CPU usage for MJPEG source cameras as it will
+ * decompress and recompress the image instead of using the camera's MJPEG image directly.
*
* @param quality JPEG compression quality (0-100), -1 for unspecified
*/
public void setCompression(int quality) {
- CameraServerJNI.setProperty(CameraServerJNI.getSinkProperty(m_handle, "compression"),
- quality);
+ CameraServerJNI.setProperty(CameraServerJNI.getSinkProperty(m_handle, "compression"), quality);
}
/**
- * Set the default compression used for non-MJPEG sources. If not set,
- * 80 is used. This function has no effect on MJPEG source cameras; use
- * SetCompression() instead to force recompression of MJPEG source images.
+ * Set the default compression used for non-MJPEG sources. If not set, 80 is used. This function
+ * has no effect on MJPEG source cameras; use SetCompression() instead to force recompression of
+ * MJPEG source images.
*
* @param quality JPEG compression quality (0-100)
*/
public void setDefaultCompression(int quality) {
- CameraServerJNI.setProperty(CameraServerJNI.getSinkProperty(m_handle, "default_compression"),
- quality);
+ CameraServerJNI.setProperty(
+ CameraServerJNI.getSinkProperty(m_handle, "default_compression"), quality);
}
}
diff --git a/cscore/src/main/java/edu/wpi/cscore/UsbCamera.java b/cscore/src/main/java/edu/wpi/first/cscore/UsbCamera.java
similarity index 68%
rename from cscore/src/main/java/edu/wpi/cscore/UsbCamera.java
rename to cscore/src/main/java/edu/wpi/first/cscore/UsbCamera.java
index 7526335..8e0817e 100644
--- a/cscore/src/main/java/edu/wpi/cscore/UsbCamera.java
+++ b/cscore/src/main/java/edu/wpi/first/cscore/UsbCamera.java
@@ -1,15 +1,10 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2020 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
-package edu.wpi.cscore;
+package edu.wpi.first.cscore;
-/**
- * A source that represents a USB camera.
- */
+/** A source that represents a USB camera. */
public class UsbCamera extends VideoCamera {
/**
* Create a source for a USB camera based on device number.
@@ -42,6 +37,8 @@
/**
* Change the path to the device.
+ *
+ * @param path New device path.
*/
void setPath(String path) {
CameraServerJNI.setUsbCameraPath(m_handle, path);
@@ -49,6 +46,8 @@
/**
* Get the path to the device.
+ *
+ * @return The device path.
*/
public String getPath() {
return CameraServerJNI.getUsbCameraPath(m_handle);
@@ -56,6 +55,8 @@
/**
* Get the full camera information for the device.
+ *
+ * @return The camera information.
*/
public UsbCameraInfo getInfo() {
return CameraServerJNI.getUsbCameraInfo(m_handle);
@@ -67,7 +68,7 @@
* @param level 0=don't display Connecting message, 1=do display message
*/
public void setConnectVerbose(int level) {
- CameraServerJNI.setProperty(CameraServerJNI.getSourceProperty(m_handle, "connect_verbose"),
- level);
+ CameraServerJNI.setProperty(
+ CameraServerJNI.getSourceProperty(m_handle, "connect_verbose"), level);
}
}
diff --git a/cscore/src/main/java/edu/wpi/first/cscore/UsbCameraInfo.java b/cscore/src/main/java/edu/wpi/first/cscore/UsbCameraInfo.java
new file mode 100644
index 0000000..df856e8
--- /dev/null
+++ b/cscore/src/main/java/edu/wpi/first/cscore/UsbCameraInfo.java
@@ -0,0 +1,53 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+package edu.wpi.first.cscore;
+
+/** USB camera information. */
+public class UsbCameraInfo {
+ /**
+ * Create a new set of UsbCameraInfo.
+ *
+ * @param dev Device number (e.g. N in '/dev/videoN' on Linux)
+ * @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, int vendorId, int productId) {
+ this.dev = dev;
+ this.path = path;
+ this.name = name;
+ this.otherPaths = otherPaths;
+ this.vendorId = vendorId;
+ this.productId = productId;
+ }
+
+ /** Device number (e.g. N in '/dev/videoN' on Linux). */
+ @SuppressWarnings("MemberName")
+ public int dev;
+
+ /** Path to device if available (e.g. '/dev/video0' on Linux). */
+ @SuppressWarnings("MemberName")
+ public String path;
+
+ /** Vendor/model name of the camera as provided by the USB driver. */
+ @SuppressWarnings("MemberName")
+ public String name;
+
+ /** Other path aliases to device (e.g. '/dev/v4l/by-id/...' etc on Linux). */
+ @SuppressWarnings("MemberName")
+ public String[] otherPaths;
+
+ /** USB vendor id. */
+ @SuppressWarnings("MemberName")
+ public int vendorId;
+
+ /** USB product id. */
+ @SuppressWarnings("MemberName")
+ public int productId;
+}
diff --git a/cscore/src/main/java/edu/wpi/cscore/VideoCamera.java b/cscore/src/main/java/edu/wpi/first/cscore/VideoCamera.java
similarity index 68%
rename from cscore/src/main/java/edu/wpi/cscore/VideoCamera.java
rename to cscore/src/main/java/edu/wpi/first/cscore/VideoCamera.java
index 0ab95f1..23cf7d6 100644
--- a/cscore/src/main/java/edu/wpi/cscore/VideoCamera.java
+++ b/cscore/src/main/java/edu/wpi/first/cscore/VideoCamera.java
@@ -1,15 +1,10 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2018 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
-package edu.wpi.cscore;
+package edu.wpi.first.cscore;
-/**
- * A source that represents a video camera.
- */
+/** A source that represents a video camera. */
public class VideoCamera extends VideoSource {
public static class WhiteBalance {
public static final int kFixedIndoor = 3000;
@@ -25,6 +20,8 @@
/**
* Set the brightness, as a percentage (0-100).
+ *
+ * @param brightness Brightness as a percentage (0-100).
*/
public synchronized void setBrightness(int brightness) {
CameraServerJNI.setCameraBrightness(m_handle, brightness);
@@ -32,48 +29,46 @@
/**
* Get the brightness, as a percentage (0-100).
+ *
+ * @return The brightness as a percentage (0-100).
*/
public synchronized int getBrightness() {
return CameraServerJNI.getCameraBrightness(m_handle);
}
- /**
- * Set the white balance to auto.
- */
+ /** Set the white balance to auto. */
public synchronized void setWhiteBalanceAuto() {
CameraServerJNI.setCameraWhiteBalanceAuto(m_handle);
}
- /**
- * Set the white balance to hold current.
- */
+ /** Set the white balance to hold current. */
public synchronized void setWhiteBalanceHoldCurrent() {
CameraServerJNI.setCameraWhiteBalanceHoldCurrent(m_handle);
}
/**
* Set the white balance to manual, with specified color temperature.
+ *
+ * @param value The specified color temperature.
*/
public synchronized void setWhiteBalanceManual(int value) {
CameraServerJNI.setCameraWhiteBalanceManual(m_handle, value);
}
- /**
- * Set the exposure to auto aperture.
- */
+ /** Set the exposure to auto aperture. */
public synchronized void setExposureAuto() {
CameraServerJNI.setCameraExposureAuto(m_handle);
}
- /**
- * Set the exposure to hold current.
- */
+ /** Set the exposure to hold current. */
public synchronized void setExposureHoldCurrent() {
CameraServerJNI.setCameraExposureHoldCurrent(m_handle);
}
/**
* Set the exposure to manual, as a percentage (0-100).
+ *
+ * @param value The exposure as a percentage (0-100).
*/
public synchronized void setExposureManual(int value) {
CameraServerJNI.setCameraExposureManual(m_handle, value);
diff --git a/cscore/src/main/java/edu/wpi/first/cscore/VideoEvent.java b/cscore/src/main/java/edu/wpi/first/cscore/VideoEvent.java
new file mode 100644
index 0000000..50f041c
--- /dev/null
+++ b/cscore/src/main/java/edu/wpi/first/cscore/VideoEvent.java
@@ -0,0 +1,166 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+package edu.wpi.first.cscore;
+
+/** Video event. */
+public class VideoEvent {
+ public enum Kind {
+ kUnknown(0x0000),
+ kSourceCreated(0x0001),
+ kSourceDestroyed(0x0002),
+ kSourceConnected(0x0004),
+ kSourceDisconnected(0x0008),
+ kSourceVideoModesUpdated(0x0010),
+ kSourceVideoModeChanged(0x0020),
+ kSourcePropertyCreated(0x0040),
+ kSourcePropertyValueUpdated(0x0080),
+ kSourcePropertyChoicesUpdated(0x0100),
+ kSinkSourceChanged(0x0200),
+ kSinkCreated(0x0400),
+ kSinkDestroyed(0x0800),
+ kSinkEnabled(0x1000),
+ kSinkDisabled(0x2000),
+ kNetworkInterfacesChanged(0x4000),
+ kTelemetryUpdated(0x8000),
+ kSinkPropertyCreated(0x10000),
+ kSinkPropertyValueUpdated(0x20000),
+ kSinkPropertyChoicesUpdated(0x40000),
+ kUsbCamerasChanged(0x80000);
+
+ private final int value;
+
+ Kind(int value) {
+ this.value = value;
+ }
+
+ public int getValue() {
+ return value;
+ }
+ }
+
+ /**
+ * Convert from the numerical representation of kind to an enum type.
+ *
+ * @param kind The numerical representation of kind
+ * @return The kind
+ */
+ public static Kind getKindFromInt(int kind) {
+ switch (kind) {
+ case 0x0001:
+ return Kind.kSourceCreated;
+ case 0x0002:
+ return Kind.kSourceDestroyed;
+ case 0x0004:
+ return Kind.kSourceConnected;
+ case 0x0008:
+ return Kind.kSourceDisconnected;
+ case 0x0010:
+ return Kind.kSourceVideoModesUpdated;
+ case 0x0020:
+ return Kind.kSourceVideoModeChanged;
+ case 0x0040:
+ return Kind.kSourcePropertyCreated;
+ case 0x0080:
+ return Kind.kSourcePropertyValueUpdated;
+ case 0x0100:
+ return Kind.kSourcePropertyChoicesUpdated;
+ case 0x0200:
+ return Kind.kSinkSourceChanged;
+ case 0x0400:
+ return Kind.kSinkCreated;
+ case 0x0800:
+ return Kind.kSinkDestroyed;
+ case 0x1000:
+ return Kind.kSinkEnabled;
+ case 0x2000:
+ return Kind.kSinkDisabled;
+ case 0x4000:
+ return Kind.kNetworkInterfacesChanged;
+ case 0x10000:
+ return Kind.kSinkPropertyCreated;
+ case 0x20000:
+ return Kind.kSinkPropertyValueUpdated;
+ case 0x40000:
+ return Kind.kSinkPropertyChoicesUpdated;
+ case 0x80000:
+ return Kind.kUsbCamerasChanged;
+ default:
+ return Kind.kUnknown;
+ }
+ }
+
+ VideoEvent(
+ int kind,
+ int source,
+ int sink,
+ String name,
+ int pixelFormat,
+ int width,
+ int height,
+ int fps,
+ int property,
+ int propertyKind,
+ int value,
+ String valueStr,
+ int listener) {
+ this.kind = getKindFromInt(kind);
+ this.sourceHandle = source;
+ this.sinkHandle = sink;
+ this.name = name;
+ this.mode = new VideoMode(pixelFormat, width, height, fps);
+ this.propertyHandle = property;
+ this.propertyKind = VideoProperty.getKindFromInt(propertyKind);
+ this.value = value;
+ this.valueStr = valueStr;
+ this.listener = listener;
+ }
+
+ @SuppressWarnings("MemberName")
+ public Kind kind;
+
+ // Valid for kSource* and kSink* respectively
+ @SuppressWarnings("MemberName")
+ public int sourceHandle;
+
+ @SuppressWarnings("MemberName")
+ public int sinkHandle;
+
+ // Source/sink/property name
+ @SuppressWarnings("MemberName")
+ public String name;
+
+ // Fields for kSourceVideoModeChanged event
+ @SuppressWarnings("MemberName")
+ public VideoMode mode;
+
+ // Fields for kSourceProperty* events
+ @SuppressWarnings("MemberName")
+ public int propertyHandle;
+
+ @SuppressWarnings("MemberName")
+ public VideoProperty.Kind propertyKind;
+
+ @SuppressWarnings("MemberName")
+ public int value;
+
+ @SuppressWarnings("MemberName")
+ public String valueStr;
+
+ // Listener that was triggered
+ @SuppressWarnings("MemberName")
+ public int listener;
+
+ public VideoSource getSource() {
+ return new VideoSource(CameraServerJNI.copySource(sourceHandle));
+ }
+
+ public VideoSink getSink() {
+ return new VideoSink(CameraServerJNI.copySink(sinkHandle));
+ }
+
+ public VideoProperty getProperty() {
+ return new VideoProperty(propertyHandle, propertyKind);
+ }
+}
diff --git a/cscore/src/main/java/edu/wpi/first/cscore/VideoException.java b/cscore/src/main/java/edu/wpi/first/cscore/VideoException.java
new file mode 100644
index 0000000..1c445c6
--- /dev/null
+++ b/cscore/src/main/java/edu/wpi/first/cscore/VideoException.java
@@ -0,0 +1,19 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+package edu.wpi.first.cscore;
+
+/** An exception raised by the camera server. */
+public class VideoException extends RuntimeException {
+ private static final long serialVersionUID = -9155939328084105145L;
+
+ public VideoException(String msg) {
+ super(msg);
+ }
+
+ @Override
+ public String toString() {
+ return "VideoException [" + super.toString() + "]";
+ }
+}
diff --git a/cscore/src/main/java/edu/wpi/first/cscore/VideoListener.java b/cscore/src/main/java/edu/wpi/first/cscore/VideoListener.java
new file mode 100644
index 0000000..0d77461
--- /dev/null
+++ b/cscore/src/main/java/edu/wpi/first/cscore/VideoListener.java
@@ -0,0 +1,126 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+package edu.wpi.first.cscore;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.function.Consumer;
+
+/**
+ * An event listener. This calls back to a desigated callback function when an event matching the
+ * specified mask is generated by the library.
+ */
+public class VideoListener implements AutoCloseable {
+ /**
+ * Create an event listener.
+ *
+ * @param listener Listener function
+ * @param eventMask Bitmask of VideoEvent.Type values
+ * @param immediateNotify Whether callback should be immediately called with a representative set
+ * of events for the current library state.
+ */
+ public VideoListener(Consumer<VideoEvent> listener, int eventMask, boolean immediateNotify) {
+ s_lock.lock();
+ try {
+ if (s_poller == 0) {
+ s_poller = CameraServerJNI.createListenerPoller();
+ startThread();
+ }
+ m_handle = CameraServerJNI.addPolledListener(s_poller, eventMask, immediateNotify);
+ s_listeners.put(m_handle, listener);
+ } finally {
+ s_lock.unlock();
+ }
+ }
+
+ @Override
+ public synchronized void close() {
+ if (m_handle != 0) {
+ s_lock.lock();
+ try {
+ s_listeners.remove(m_handle);
+ } finally {
+ s_lock.unlock();
+ }
+ CameraServerJNI.removeListener(m_handle);
+ m_handle = 0;
+ }
+ }
+
+ public boolean isValid() {
+ return m_handle != 0;
+ }
+
+ private int m_handle;
+
+ private static final ReentrantLock s_lock = new ReentrantLock();
+ private static final Map<Integer, Consumer<VideoEvent>> s_listeners = new HashMap<>();
+ private static Thread s_thread;
+ private static int s_poller;
+ private static boolean s_waitQueue;
+ private static final Condition s_waitQueueCond = s_lock.newCondition();
+
+ @SuppressWarnings("PMD.AvoidCatchingThrowable")
+ private static void startThread() {
+ s_thread =
+ new Thread(
+ () -> {
+ boolean wasInterrupted = false;
+ while (!Thread.interrupted()) {
+ VideoEvent[] events;
+ try {
+ events = CameraServerJNI.pollListener(s_poller);
+ } catch (InterruptedException ex) {
+ s_lock.lock();
+ try {
+ if (s_waitQueue) {
+ s_waitQueue = false;
+ s_waitQueueCond.signalAll();
+ continue;
+ }
+ } finally {
+ s_lock.unlock();
+ }
+ Thread.currentThread().interrupt();
+ // don't try to destroy poller, as its handle is likely no longer valid
+ wasInterrupted = true;
+ break;
+ }
+ for (VideoEvent event : events) {
+ Consumer<VideoEvent> listener;
+ s_lock.lock();
+ try {
+ listener = s_listeners.get(event.listener);
+ } finally {
+ s_lock.unlock();
+ }
+ if (listener != null) {
+ try {
+ listener.accept(event);
+ } catch (Throwable throwable) {
+ System.err.println(
+ "Unhandled exception during listener callback: " + throwable.toString());
+ throwable.printStackTrace();
+ }
+ }
+ }
+ }
+ s_lock.lock();
+ try {
+ if (!wasInterrupted) {
+ CameraServerJNI.destroyListenerPoller(s_poller);
+ }
+ s_poller = 0;
+ } finally {
+ s_lock.unlock();
+ }
+ },
+ "VideoListener");
+ s_thread.setDaemon(true);
+ s_thread.start();
+ }
+}
diff --git a/cscore/src/main/java/edu/wpi/first/cscore/VideoMode.java b/cscore/src/main/java/edu/wpi/first/cscore/VideoMode.java
new file mode 100644
index 0000000..726b210
--- /dev/null
+++ b/cscore/src/main/java/edu/wpi/first/cscore/VideoMode.java
@@ -0,0 +1,79 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+package edu.wpi.first.cscore;
+
+/** Video mode. */
+public class VideoMode {
+ public enum PixelFormat {
+ kUnknown(0),
+ kMJPEG(1),
+ kYUYV(2),
+ kRGB565(3),
+ kBGR(4),
+ kGray(5);
+
+ private final int value;
+
+ PixelFormat(int value) {
+ this.value = value;
+ }
+
+ public int getValue() {
+ return value;
+ }
+ }
+
+ private static final PixelFormat[] m_pixelFormatValues = PixelFormat.values();
+
+ public static PixelFormat getPixelFormatFromInt(int pixelFormat) {
+ return m_pixelFormatValues[pixelFormat];
+ }
+
+ /**
+ * Create a new video mode.
+ *
+ * @param pixelFormat The pixel format enum as an integer.
+ * @param width The image width in pixels.
+ * @param height The image height in pixels.
+ * @param fps The camera's frames per second.
+ */
+ public VideoMode(int pixelFormat, int width, int height, int fps) {
+ this.pixelFormat = getPixelFormatFromInt(pixelFormat);
+ this.width = width;
+ this.height = height;
+ this.fps = fps;
+ }
+
+ /**
+ * Create a new video mode.
+ *
+ * @param pixelFormat The pixel format.
+ * @param width The image width in pixels.
+ * @param height The image height in pixels.
+ * @param fps The camera's frames per second.
+ */
+ public VideoMode(PixelFormat pixelFormat, int width, int height, int fps) {
+ this.pixelFormat = pixelFormat;
+ this.width = width;
+ this.height = height;
+ this.fps = fps;
+ }
+
+ /** Pixel format. */
+ @SuppressWarnings("MemberName")
+ public PixelFormat pixelFormat;
+
+ /** Width in pixels. */
+ @SuppressWarnings("MemberName")
+ public int width;
+
+ /** Height in pixels. */
+ @SuppressWarnings("MemberName")
+ public int height;
+
+ /** Frames per second. */
+ @SuppressWarnings("MemberName")
+ public int fps;
+}
diff --git a/cscore/src/main/java/edu/wpi/cscore/VideoProperty.java b/cscore/src/main/java/edu/wpi/first/cscore/VideoProperty.java
similarity index 71%
rename from cscore/src/main/java/edu/wpi/cscore/VideoProperty.java
rename to cscore/src/main/java/edu/wpi/first/cscore/VideoProperty.java
index 407e107..8179ba3 100644
--- a/cscore/src/main/java/edu/wpi/cscore/VideoProperty.java
+++ b/cscore/src/main/java/edu/wpi/first/cscore/VideoProperty.java
@@ -1,20 +1,18 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2018 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
-package edu.wpi.cscore;
+package edu.wpi.first.cscore;
-/**
- * A source or sink property.
- */
+/** A source or sink property. */
public class VideoProperty {
public enum Kind {
- kNone(0), kBoolean(1), kInteger(2), kString(4), kEnum(8);
+ kNone(0),
+ kBoolean(1),
+ kInteger(2),
+ kString(4),
+ kEnum(8);
- @SuppressWarnings("MemberName")
private final int value;
Kind(int value) {
@@ -34,11 +32,16 @@
*/
public static Kind getKindFromInt(int kind) {
switch (kind) {
- case 1: return Kind.kBoolean;
- case 2: return Kind.kInteger;
- case 4: return Kind.kString;
- case 8: return Kind.kEnum;
- default: return Kind.kNone;
+ case 1:
+ return Kind.kBoolean;
+ case 2:
+ return Kind.kInteger;
+ case 4:
+ return Kind.kString;
+ case 8:
+ return Kind.kEnum;
+ default:
+ return Kind.kNone;
}
}
diff --git a/cscore/src/main/java/edu/wpi/cscore/VideoSink.java b/cscore/src/main/java/edu/wpi/first/cscore/VideoSink.java
similarity index 71%
rename from cscore/src/main/java/edu/wpi/cscore/VideoSink.java
rename to cscore/src/main/java/edu/wpi/first/cscore/VideoSink.java
index 107f6d9..8b07f46 100644
--- a/cscore/src/main/java/edu/wpi/cscore/VideoSink.java
+++ b/cscore/src/main/java/edu/wpi/first/cscore/VideoSink.java
@@ -1,22 +1,20 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
-package edu.wpi.cscore;
+package edu.wpi.first.cscore;
/**
- * A source for video that provides a sequence of frames. Each frame may
- * consist of multiple images (e.g. from a stereo or depth camera); these
- * are called channels.
+ * A source for video that provides a sequence of frames. Each frame may consist of multiple images
+ * (e.g. from a stereo or depth camera); these are called channels.
*/
public class VideoSink implements AutoCloseable {
public enum Kind {
- kUnknown(0), kMjpeg(2), kCv(4), kRaw(8);
+ kUnknown(0),
+ kMjpeg(2),
+ kCv(4),
+ kRaw(8);
- @SuppressWarnings("MemberName")
private final int value;
Kind(int value) {
@@ -36,9 +34,12 @@
*/
public static Kind getKindFromInt(int kind) {
switch (kind) {
- case 2: return Kind.kMjpeg;
- case 4: return Kind.kCv;
- default: return Kind.kUnknown;
+ case 2:
+ return Kind.kMjpeg;
+ case 4:
+ return Kind.kCv;
+ default:
+ return Kind.kUnknown;
}
}
@@ -84,21 +85,27 @@
/**
* Get the kind of the sink.
+ *
+ * @return The kind of the sink.
*/
public Kind getKind() {
return getKindFromInt(CameraServerJNI.getSinkKind(m_handle));
}
/**
- * Get the name of the sink. The name is an arbitrary identifier
- * provided when the sink is created, and should be unique.
+ * Get the name of the sink. The name is an arbitrary identifier provided when the sink is
+ * created, and should be unique.
+ *
+ * @return The name of the sink.
*/
public String getName() {
return CameraServerJNI.getSinkName(m_handle);
}
/**
- * Get the sink description. This is sink-kind specific.
+ * Get the sink description. This is sink-kind specific.
+ *
+ * @return The sink description.
*/
public String getDescription() {
return CameraServerJNI.getSinkDescription(m_handle);
@@ -108,8 +115,7 @@
* Get a property of the sink.
*
* @param name Property name
- * @return Property (kind Property::kNone if no property with
- * the given name exists)
+ * @return Property (kind Property::kNone if no property with the given name exists)
*/
public VideoProperty getProperty(String name) {
return new VideoProperty(CameraServerJNI.getSinkProperty(m_handle, name));
@@ -117,8 +123,9 @@
/**
* Enumerate all properties of this sink.
+ *
+ * @return List of properties.
*/
- @SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops")
public VideoProperty[] enumerateProperties() {
int[] handles = CameraServerJNI.enumerateSinkProperties(m_handle);
VideoProperty[] rv = new VideoProperty[handles.length];
@@ -161,9 +168,8 @@
}
/**
- * Configure which source should provide frames to this sink. Each sink
- * can accept frames from only a single source, but a single source can
- * provide frames to multiple clients.
+ * Configure which source should provide frames to this sink. Each sink can accept frames from
+ * only a single source, but a single source can provide frames to multiple clients.
*
* @param source Source
*/
@@ -190,12 +196,11 @@
* Get a property of the associated source.
*
* @param name Property name
- * @return Property (kind Property::kNone if no property with
- * the given name exists or no source connected)
+ * @return Property (kind Property::kNone if no property with the given name exists or no source
+ * connected)
*/
public VideoProperty getSourceProperty(String name) {
- return new VideoProperty(
- CameraServerJNI.getSinkSourceProperty(m_handle, name));
+ return new VideoProperty(CameraServerJNI.getSinkSourceProperty(m_handle, name));
}
/**
@@ -203,7 +208,6 @@
*
* @return Vector of sinks.
*/
- @SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops")
public static VideoSink[] enumerateSinks() {
int[] handles = CameraServerJNI.enumerateSinks();
VideoSink[] rv = new VideoSink[handles.length];
diff --git a/cscore/src/main/java/edu/wpi/cscore/VideoSource.java b/cscore/src/main/java/edu/wpi/first/cscore/VideoSource.java
similarity index 72%
rename from cscore/src/main/java/edu/wpi/cscore/VideoSource.java
rename to cscore/src/main/java/edu/wpi/first/cscore/VideoSource.java
index 51d3821..0ae5add 100644
--- a/cscore/src/main/java/edu/wpi/cscore/VideoSource.java
+++ b/cscore/src/main/java/edu/wpi/first/cscore/VideoSource.java
@@ -1,22 +1,21 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
-package edu.wpi.cscore;
+package edu.wpi.first.cscore;
/**
- * A source for video that provides a sequence of frames. Each frame may
- * consist of multiple images (e.g. from a stereo or depth camera); these
- * are called channels.
+ * A source for video that provides a sequence of frames. Each frame may consist of multiple images
+ * (e.g. from a stereo or depth camera); these are called channels.
*/
public class VideoSource implements AutoCloseable {
public enum Kind {
- kUnknown(0), kUsb(1), kHttp(2), kCv(4), kRaw(8);
+ kUnknown(0),
+ kUsb(1),
+ kHttp(2),
+ kCv(4),
+ kRaw(8);
- @SuppressWarnings("MemberName")
private final int value;
Kind(int value) {
@@ -28,29 +27,22 @@
}
}
- /**
- * Connection strategy.
- */
+ /** Connection strategy. */
public enum ConnectionStrategy {
/**
- * Automatically connect or disconnect based on whether any sinks are
- * connected to this source. This is the default behavior.
+ * Automatically connect or disconnect based on whether any sinks are connected to this source.
+ * This is the default behavior.
*/
kAutoManage(0),
- /**
- * Try to keep the connection open regardless of whether any sinks are
- * connected.
- */
+ /** Try to keep the connection open regardless of whether any sinks are connected. */
kKeepOpen(1),
/**
- * Never open the connection. If this is set when the connection is open,
- * close the connection.
+ * Never open the connection. If this is set when the connection is open, close the connection.
*/
kForceClose(2);
- @SuppressWarnings("MemberName")
private final int value;
ConnectionStrategy(int value) {
@@ -70,10 +62,14 @@
*/
public static Kind getKindFromInt(int kind) {
switch (kind) {
- case 1: return Kind.kUsb;
- case 2: return Kind.kHttp;
- case 4: return Kind.kCv;
- default: return Kind.kUnknown;
+ case 1:
+ return Kind.kUsb;
+ case 2:
+ return Kind.kHttp;
+ case 4:
+ return Kind.kCv;
+ default:
+ return Kind.kUnknown;
}
}
@@ -119,21 +115,27 @@
/**
* Get the kind of the source.
+ *
+ * @return The kind of the source.
*/
public Kind getKind() {
return getKindFromInt(CameraServerJNI.getSourceKind(m_handle));
}
/**
- * Get the name of the source. The name is an arbitrary identifier
- * provided when the source is created, and should be unique.
+ * Get the name of the source. The name is an arbitrary identifier provided when the source is
+ * created, and should be unique.
+ *
+ * @return The name of the source.
*/
public String getName() {
return CameraServerJNI.getSourceName(m_handle);
}
/**
- * Get the source description. This is source-kind specific.
+ * Get the source description. This is source-kind specific.
+ *
+ * @return The source description.
*/
public String getDescription() {
return CameraServerJNI.getSourceDescription(m_handle);
@@ -141,6 +143,7 @@
/**
* Get the last time a frame was captured.
+ *
* @return Time in 1 us increments.
*/
public long getLastFrameTime() {
@@ -148,12 +151,11 @@
}
/**
- * Sets the connection strategy. By default, the source will automatically
- * connect or disconnect based on whether any sinks are connected.
+ * Sets the connection strategy. By default, the source will automatically connect or disconnect
+ * based on whether any sinks are connected.
*
- * <p>This function is non-blocking; look for either a connection open or
- * close event or call {@link #isConnected()} to determine the connection
- * state.
+ * <p>This function is non-blocking; look for either a connection open or close event or call
+ * {@link #isConnected()} to determine the connection state.
*
* @param strategy connection strategy (auto, keep open, or force close)
*/
@@ -162,15 +164,17 @@
}
/**
- * Returns if the source currently connected to whatever is providing the images.
+ * Returns true if the source currently connected to whatever is providing the images.
+ *
+ * @return True if the source currently connected to whatever is providing the images.
*/
public boolean isConnected() {
return CameraServerJNI.isSourceConnected(m_handle);
}
/**
- * Gets source enable status. This is determined with a combination of
- * connection strategy and the number of sinks connected.
+ * Gets source enable status. This is determined with a combination of connection strategy and the
+ * number of sinks connected.
*
* @return True if enabled, false otherwise.
*/
@@ -182,8 +186,7 @@
* Get a property.
*
* @param name Property name
- * @return Property contents (of kind Property::kNone if no property with
- * the given name exists)
+ * @return Property contents (of kind Property::kNone if no property with the given name exists)
*/
public VideoProperty getProperty(String name) {
return new VideoProperty(CameraServerJNI.getSourceProperty(m_handle, name));
@@ -191,8 +194,9 @@
/**
* Enumerate all properties of this source.
+ *
+ * @return Array of video properties.
*/
- @SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops")
public VideoProperty[] enumerateProperties() {
int[] handles = CameraServerJNI.enumerateSourceProperties(m_handle);
VideoProperty[] rv = new VideoProperty[handles.length];
@@ -204,6 +208,8 @@
/**
* Get the current video mode.
+ *
+ * @return The current video mode.
*/
public VideoMode getVideoMode() {
return CameraServerJNI.getSourceVideoMode(m_handle);
@@ -211,14 +217,13 @@
/**
* Set the video mode.
+ *
* @param mode Video mode
+ * @return True if set successfully.
*/
public boolean setVideoMode(VideoMode mode) {
- return CameraServerJNI.setSourceVideoMode(m_handle,
- mode.pixelFormat.getValue(),
- mode.width,
- mode.height,
- mode.fps);
+ return CameraServerJNI.setSourceVideoMode(
+ m_handle, mode.pixelFormat.getValue(), mode.width, mode.height, mode.fps);
}
/**
@@ -307,31 +312,33 @@
/**
* Get the actual FPS.
*
- * <p>CameraServerJNI#setTelemetryPeriod() must be called for this to be valid
- * (throws VisionException if telemetry is not enabled).
+ * <p>CameraServerJNI#setTelemetryPeriod() must be called for this to be valid (throws
+ * VisionException if telemetry is not enabled).
*
* @return Actual FPS averaged over the telemetry period.
*/
public double getActualFPS() {
- return CameraServerJNI.getTelemetryAverageValue(m_handle,
- CameraServerJNI.TelemetryKind.kSourceFramesReceived);
+ return CameraServerJNI.getTelemetryAverageValue(
+ m_handle, CameraServerJNI.TelemetryKind.kSourceFramesReceived);
}
/**
* Get the data rate (in bytes per second).
*
- * <p>CameraServerJNI#setTelemetryPeriod() must be called for this to be valid
- * (throws VisionException if telemetry is not enabled).
+ * <p>CameraServerJNI#setTelemetryPeriod() must be called for this to be valid (throws
+ * VisionException if telemetry is not enabled).
*
* @return Data rate averaged over the telemetry period.
*/
public double getActualDataRate() {
- return CameraServerJNI.getTelemetryAverageValue(m_handle,
- CameraServerJNI.TelemetryKind.kSourceBytesReceived);
+ return CameraServerJNI.getTelemetryAverageValue(
+ m_handle, CameraServerJNI.TelemetryKind.kSourceBytesReceived);
}
/**
* Enumerate all known video modes for this source.
+ *
+ * @return Vector of video modes.
*/
public VideoMode[] enumerateVideoModes() {
return CameraServerJNI.enumerateSourceVideoModes(m_handle);
@@ -342,7 +349,6 @@
*
* @return Vector of sinks.
*/
- @SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops")
public VideoSink[] enumerateSinks() {
int[] handles = CameraServerJNI.enumerateSourceSinks(m_handle);
VideoSink[] rv = new VideoSink[handles.length];
@@ -357,7 +363,6 @@
*
* @return Vector of sources.
*/
- @SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops")
public static VideoSource[] enumerateSources() {
int[] handles = CameraServerJNI.enumerateSources();
VideoSource[] rv = new VideoSource[handles.length];
diff --git a/cscore/src/main/java/edu/wpi/first/cscore/raw/RawFrame.java b/cscore/src/main/java/edu/wpi/first/cscore/raw/RawFrame.java
new file mode 100644
index 0000000..5f62481
--- /dev/null
+++ b/cscore/src/main/java/edu/wpi/first/cscore/raw/RawFrame.java
@@ -0,0 +1,156 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+package edu.wpi.first.cscore.raw;
+
+import edu.wpi.first.cscore.CameraServerJNI;
+import java.nio.ByteBuffer;
+
+/**
+ * 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.
+ *
+ * @param dataByteBuffer A ByteBuffer pointing to the frame data.
+ * @param dataPtr A long (a char* in native code) pointing to the frame data.
+ * @param totalData The total length of the data stored in the frame.
+ * @param width The width of the frame.
+ * @param height The height of the frame.
+ * @param pixelFormat The PixelFormat of the frame.
+ */
+ 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.
+ *
+ * @return 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.
+ *
+ * @return A ByteBuffer pointing to the frame data.
+ */
+ 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.
+ *
+ * @return A long pointing to the frame data.
+ */
+ public long getDataPtr() {
+ return m_dataPtr;
+ }
+
+ /**
+ * Get the total length of the data stored in the frame.
+ *
+ * @return The total length of the data stored in the frame.
+ */
+ public int getTotalData() {
+ return m_totalData;
+ }
+
+ /**
+ * Get the width of the frame.
+ *
+ * @return The width of the frame.
+ */
+ public int getWidth() {
+ return m_width;
+ }
+
+ /**
+ * Set the width of the frame.
+ *
+ * @param width The width of the frame.
+ */
+ public void setWidth(int width) {
+ this.m_width = width;
+ }
+
+ /**
+ * Get the height of the frame.
+ *
+ * @return The height of the frame.
+ */
+ public int getHeight() {
+ return m_height;
+ }
+
+ /**
+ * Set the height of the frame.
+ *
+ * @param height The height of the frame.
+ */
+ public void setHeight(int height) {
+ this.m_height = height;
+ }
+
+ /**
+ * Get the PixelFormat of the frame.
+ *
+ * @return The PixelFormat of the frame.
+ */
+ public int getPixelFormat() {
+ return m_pixelFormat;
+ }
+
+ /**
+ * Set the PixelFormat of the frame.
+ *
+ * @param pixelFormat The PixelFormat of the frame.
+ */
+ public void setPixelFormat(int pixelFormat) {
+ this.m_pixelFormat = pixelFormat;
+ }
+}
diff --git a/cscore/src/main/java/edu/wpi/first/cscore/raw/RawSink.java b/cscore/src/main/java/edu/wpi/first/cscore/raw/RawSink.java
new file mode 100644
index 0000000..ae5b0ef
--- /dev/null
+++ b/cscore/src/main/java/edu/wpi/first/cscore/raw/RawSink.java
@@ -0,0 +1,63 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+package edu.wpi.first.cscore.raw;
+
+import edu.wpi.first.cscore.CameraServerJNI;
+import edu.wpi.first.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.
+ *
+ * @param frame The frame object in which to store the image.
+ * @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.
+ *
+ * @param frame The frame object in which to store the image.
+ * @param timeout The frame timeout in seconds.
+ * @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.
+ *
+ * @param frame The frame object in which to store the image.
+ * @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);
+ }
+}
diff --git a/cscore/src/main/java/edu/wpi/first/cscore/raw/RawSource.java b/cscore/src/main/java/edu/wpi/first/cscore/raw/RawSource.java
new file mode 100644
index 0000000..f1be050
--- /dev/null
+++ b/cscore/src/main/java/edu/wpi/first/cscore/raw/RawSource.java
@@ -0,0 +1,78 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+package edu.wpi.first.cscore.raw;
+
+import edu.wpi.first.cscore.CameraServerJNI;
+import edu.wpi.first.cscore.ImageSource;
+import edu.wpi.first.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);
+ }
+}
diff --git a/cscore/src/main/native/cpp/ConfigurableSourceImpl.cpp b/cscore/src/main/native/cpp/ConfigurableSourceImpl.cpp
index 3ba1784..16452f1 100644
--- a/cscore/src/main/native/cpp/ConfigurableSourceImpl.cpp
+++ b/cscore/src/main/native/cpp/ConfigurableSourceImpl.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2018-2020 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#include "ConfigurableSourceImpl.h"
@@ -16,7 +13,7 @@
using namespace cs;
-ConfigurableSourceImpl::ConfigurableSourceImpl(const wpi::Twine& name,
+ConfigurableSourceImpl::ConfigurableSourceImpl(std::string_view name,
wpi::Logger& logger,
Notifier& notifier,
Telemetry& telemetry,
@@ -26,7 +23,7 @@
m_videoModes.push_back(m_mode);
}
-ConfigurableSourceImpl::~ConfigurableSourceImpl() {}
+ConfigurableSourceImpl::~ConfigurableSourceImpl() = default;
void ConfigurableSourceImpl::Start() {
m_notifier.NotifySource(*this, CS_SOURCE_CONNECTED);
@@ -53,11 +50,11 @@
// ignore
}
-void ConfigurableSourceImpl::NotifyError(const wpi::Twine& msg) {
+void ConfigurableSourceImpl::NotifyError(std::string_view msg) {
PutError(msg, wpi::Now());
}
-int ConfigurableSourceImpl::CreateProperty(const wpi::Twine& name,
+int ConfigurableSourceImpl::CreateProperty(std::string_view name,
CS_PropertyKind kind, int minimum,
int maximum, int step,
int defaultValue, int value) {
@@ -78,12 +75,12 @@
value = prop.value;
});
m_notifier.NotifySourceProperty(*this, CS_SOURCE_PROPERTY_CREATED, name, ndx,
- kind, value, wpi::Twine{});
+ kind, value, {});
return ndx;
}
int ConfigurableSourceImpl::CreateProperty(
- const wpi::Twine& name, CS_PropertyKind kind, int minimum, int maximum,
+ std::string_view name, CS_PropertyKind kind, int minimum, int maximum,
int step, int defaultValue, int value,
std::function<void(CS_Property property)> onChange) {
// TODO
@@ -91,7 +88,7 @@
}
void ConfigurableSourceImpl::SetEnumPropertyChoices(
- int property, wpi::ArrayRef<std::string> choices, CS_Status* status) {
+ int property, wpi::span<const std::string> choices, CS_Status* status) {
std::scoped_lock lock(m_mutex);
auto prop = GetProperty(property);
if (!prop) {
@@ -102,8 +99,8 @@
*status = CS_WRONG_PROPERTY_TYPE;
return;
}
- prop->enumChoices = choices;
+ prop->enumChoices.assign(choices.begin(), choices.end());
m_notifier.NotifySourceProperty(*this, CS_SOURCE_PROPERTY_CHOICES_UPDATED,
prop->name, property, CS_PROP_ENUM,
- prop->value, wpi::Twine{});
+ prop->value, {});
}
diff --git a/cscore/src/main/native/cpp/ConfigurableSourceImpl.h b/cscore/src/main/native/cpp/ConfigurableSourceImpl.h
index a10f27e..bb9f3ed 100644
--- a/cscore/src/main/native/cpp/ConfigurableSourceImpl.h
+++ b/cscore/src/main/native/cpp/ConfigurableSourceImpl.h
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#ifndef CSCORE_CONFIGURABLESOURCEIMPL_H_
#define CSCORE_CONFIGURABLESOURCEIMPL_H_
@@ -12,10 +9,10 @@
#include <functional>
#include <memory>
#include <string>
+#include <string_view>
#include <vector>
-#include <wpi/ArrayRef.h>
-#include <wpi/Twine.h>
+#include <wpi/span.h>
#include "SourceImpl.h"
@@ -23,7 +20,7 @@
class ConfigurableSourceImpl : public SourceImpl {
protected:
- ConfigurableSourceImpl(const wpi::Twine& name, wpi::Logger& logger,
+ ConfigurableSourceImpl(std::string_view name, wpi::Logger& logger,
Notifier& notifier, Telemetry& telemetry,
const VideoMode& mode);
@@ -38,13 +35,14 @@
void NumSinksEnabledChanged() override;
// OpenCV-specific functions
- void NotifyError(const wpi::Twine& msg);
- int CreateProperty(const wpi::Twine& name, CS_PropertyKind kind, int minimum,
+ void NotifyError(std::string_view msg);
+ int CreateProperty(std::string_view 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 CreateProperty(std::string_view 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,
+ void SetEnumPropertyChoices(int property,
+ wpi::span<const std::string> choices,
CS_Status* status);
private:
diff --git a/cscore/src/main/native/cpp/CvSinkImpl.cpp b/cscore/src/main/native/cpp/CvSinkImpl.cpp
index 7ba505a..dbda6c6 100644
--- a/cscore/src/main/native/cpp/CvSinkImpl.cpp
+++ b/cscore/src/main/native/cpp/CvSinkImpl.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#include "CvSinkImpl.h"
@@ -21,28 +18,34 @@
using namespace cs;
-CvSinkImpl::CvSinkImpl(const wpi::Twine& name, wpi::Logger& logger,
+CvSinkImpl::CvSinkImpl(std::string_view name, wpi::Logger& logger,
Notifier& notifier, Telemetry& telemetry)
: SinkImpl{name, logger, notifier, telemetry} {
m_active = true;
// m_thread = std::thread(&CvSinkImpl::ThreadMain, this);
}
-CvSinkImpl::CvSinkImpl(const wpi::Twine& name, wpi::Logger& logger,
+CvSinkImpl::CvSinkImpl(std::string_view name, wpi::Logger& logger,
Notifier& notifier, Telemetry& telemetry,
std::function<void(uint64_t time)> processFrame)
: SinkImpl{name, logger, notifier, telemetry} {}
-CvSinkImpl::~CvSinkImpl() { Stop(); }
+CvSinkImpl::~CvSinkImpl() {
+ Stop();
+}
void CvSinkImpl::Stop() {
m_active = false;
// wake up any waiters by forcing an empty frame to be sent
- if (auto source = GetSource()) source->Wakeup();
+ if (auto source = GetSource()) {
+ source->Wakeup();
+ }
// join thread
- if (m_thread.joinable()) m_thread.join();
+ if (m_thread.joinable()) {
+ m_thread.join();
+ }
}
uint64_t CvSinkImpl::GrabFrame(cv::Mat& image) {
@@ -107,9 +110,11 @@
std::this_thread::sleep_for(std::chrono::seconds(1));
continue;
}
- SDEBUG4("waiting for frame");
+ SDEBUG4("{}", "waiting for frame");
Frame frame = source->GetNextFrame(); // blocks
- if (!m_active) break;
+ 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));
@@ -122,14 +127,14 @@
namespace cs {
-CS_Sink CreateCvSink(const wpi::Twine& name, CS_Status* status) {
+CS_Sink CreateCvSink(std::string_view name, CS_Status* status) {
auto& inst = Instance::GetInstance();
return inst.CreateSink(
CS_SINK_CV, std::make_shared<CvSinkImpl>(name, inst.logger, inst.notifier,
inst.telemetry));
}
-CS_Sink CreateCvSinkCallback(const wpi::Twine& name,
+CS_Sink CreateCvSinkCallback(std::string_view name,
std::function<void(uint64_t time)> processFrame,
CS_Status* status) {
auto& inst = Instance::GetInstance();
@@ -140,7 +145,7 @@
static constexpr unsigned SinkMask = CS_SINK_CV | CS_SINK_RAW;
-void SetSinkDescription(CS_Sink sink, const wpi::Twine& description,
+void SetSinkDescription(CS_Sink sink, std::string_view description,
CS_Status* status) {
auto data = Instance::GetInstance().GetSink(sink);
if (!data || (data->kind & SinkMask) == 0) {
@@ -178,12 +183,12 @@
return static_cast<CvSinkImpl&>(*data->sink).GetError();
}
-wpi::StringRef GetSinkError(CS_Sink sink, wpi::SmallVectorImpl<char>& buf,
- CS_Status* status) {
+std::string_view GetSinkError(CS_Sink sink, wpi::SmallVectorImpl<char>& buf,
+ CS_Status* status) {
auto data = Instance::GetInstance().GetSink(sink);
if (!data || (data->kind & SinkMask) == 0) {
*status = CS_INVALID_HANDLE;
- return wpi::StringRef{};
+ return {};
}
return static_cast<CvSinkImpl&>(*data->sink).GetError(buf);
}
@@ -243,7 +248,9 @@
char* CS_GetSinkError(CS_Sink sink, CS_Status* status) {
wpi::SmallString<128> buf;
auto str = cs::GetSinkError(sink, buf, status);
- if (*status != 0) return nullptr;
+ if (*status != 0) {
+ return nullptr;
+ }
return cs::ConvertToC(str);
}
diff --git a/cscore/src/main/native/cpp/CvSinkImpl.h b/cscore/src/main/native/cpp/CvSinkImpl.h
index 9b7820f..ad63a20 100644
--- a/cscore/src/main/native/cpp/CvSinkImpl.h
+++ b/cscore/src/main/native/cpp/CvSinkImpl.h
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2018 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#ifndef CSCORE_CVSINKIMPL_H_
#define CSCORE_CVSINKIMPL_H_
@@ -12,10 +9,10 @@
#include <atomic>
#include <functional>
+#include <string_view>
#include <thread>
#include <opencv2/core/core.hpp>
-#include <wpi/Twine.h>
#include <wpi/condition_variable.h>
#include "Frame.h"
@@ -27,9 +24,9 @@
class CvSinkImpl : public SinkImpl {
public:
- CvSinkImpl(const wpi::Twine& name, wpi::Logger& logger, Notifier& notifier,
+ CvSinkImpl(std::string_view name, wpi::Logger& logger, Notifier& notifier,
Telemetry& telemetry);
- CvSinkImpl(const wpi::Twine& name, wpi::Logger& logger, Notifier& notifier,
+ CvSinkImpl(std::string_view name, wpi::Logger& logger, Notifier& notifier,
Telemetry& telemetry,
std::function<void(uint64_t time)> processFrame);
~CvSinkImpl() override;
diff --git a/cscore/src/main/native/cpp/CvSourceImpl.cpp b/cscore/src/main/native/cpp/CvSourceImpl.cpp
index 49b9d28..7cd4fe0 100644
--- a/cscore/src/main/native/cpp/CvSourceImpl.cpp
+++ b/cscore/src/main/native/cpp/CvSourceImpl.cpp
@@ -1,16 +1,12 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#include "CvSourceImpl.h"
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
-#include <wpi/STLExtras.h>
#include <wpi/timestamp.h>
#include "Handle.h"
@@ -22,20 +18,21 @@
using namespace cs;
-CvSourceImpl::CvSourceImpl(const wpi::Twine& name, wpi::Logger& logger,
+CvSourceImpl::CvSourceImpl(std::string_view name, wpi::Logger& logger,
Notifier& notifier, Telemetry& telemetry,
const VideoMode& mode)
: ConfigurableSourceImpl{name, logger, notifier, telemetry, mode} {}
-CvSourceImpl::~CvSourceImpl() {}
+CvSourceImpl::~CvSourceImpl() = default;
void CvSourceImpl::PutFrame(cv::Mat& image) {
// We only support 8-bit images; convert if necessary.
cv::Mat finalImage;
- if (image.depth() == CV_8U)
+ if (image.depth() == CV_8U) {
finalImage = image;
- else
+ } else {
image.convertTo(finalImage, CV_8U);
+ }
std::unique_ptr<Image> dest;
switch (image.channels()) {
@@ -55,8 +52,7 @@
cv::cvtColor(finalImage, dest->AsMat(), cv::COLOR_BGRA2BGR);
break;
default:
- SERROR("PutFrame: " << image.channels()
- << "-channel images not supported");
+ SERROR("PutFrame: {}-channel images not supported", image.channels());
return;
}
SourceImpl::PutFrame(std::move(dest), wpi::Now());
@@ -64,7 +60,7 @@
namespace cs {
-CS_Source CreateCvSource(const wpi::Twine& name, const VideoMode& mode,
+CS_Source CreateCvSource(std::string_view name, const VideoMode& mode,
CS_Status* status) {
auto& inst = Instance::GetInstance();
return inst.CreateSource(CS_SOURCE_CV, std::make_shared<CvSourceImpl>(
@@ -83,7 +79,7 @@
static constexpr unsigned SourceMask = CS_SINK_CV | CS_SINK_RAW;
-void NotifySourceError(CS_Source source, const wpi::Twine& msg,
+void NotifySourceError(CS_Source source, std::string_view msg,
CS_Status* status) {
auto data = Instance::GetInstance().GetSource(source);
if (!data || (data->kind & SourceMask) == 0) {
@@ -102,7 +98,7 @@
static_cast<CvSourceImpl&>(*data->source).SetConnected(connected);
}
-void SetSourceDescription(CS_Source source, const wpi::Twine& description,
+void SetSourceDescription(CS_Source source, std::string_view description,
CS_Status* status) {
auto data = Instance::GetInstance().GetSource(source);
if (!data || (data->kind & SourceMask) == 0) {
@@ -112,7 +108,7 @@
static_cast<CvSourceImpl&>(*data->source).SetDescription(description);
}
-CS_Property CreateSourceProperty(CS_Source source, const wpi::Twine& name,
+CS_Property CreateSourceProperty(CS_Source source, std::string_view name,
CS_PropertyKind kind, int minimum, int maximum,
int step, int defaultValue, int value,
CS_Status* status) {
@@ -128,7 +124,7 @@
}
CS_Property CreateSourcePropertyCallback(
- CS_Source source, const wpi::Twine& name, CS_PropertyKind kind, int minimum,
+ CS_Source source, std::string_view name, CS_PropertyKind kind, int minimum,
int maximum, int step, int defaultValue, int value,
std::function<void(CS_Property property)> onChange, CS_Status* status) {
auto data = Instance::GetInstance().GetSource(source);
@@ -143,7 +139,7 @@
}
void SetSourceEnumPropertyChoices(CS_Source source, CS_Property property,
- wpi::ArrayRef<std::string> choices,
+ wpi::span<const std::string> choices,
CS_Status* status) {
auto data = Instance::GetInstance().GetSource(source);
if (!data || (data->kind & SourceMask) == 0) {
@@ -227,7 +223,9 @@
CS_Status* status) {
wpi::SmallVector<std::string, 8> vec;
vec.reserve(count);
- for (int i = 0; i < count; ++i) vec.push_back(choices[i]);
+ for (int i = 0; i < count; ++i) {
+ vec.push_back(choices[i]);
+ }
return cs::SetSourceEnumPropertyChoices(source, property, vec, status);
}
diff --git a/cscore/src/main/native/cpp/CvSourceImpl.h b/cscore/src/main/native/cpp/CvSourceImpl.h
index 978d012..fba7131 100644
--- a/cscore/src/main/native/cpp/CvSourceImpl.h
+++ b/cscore/src/main/native/cpp/CvSourceImpl.h
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#ifndef CSCORE_CVSOURCEIMPL_H_
#define CSCORE_CVSOURCEIMPL_H_
@@ -12,11 +9,10 @@
#include <functional>
#include <memory>
#include <string>
+#include <string_view>
#include <vector>
#include <opencv2/core/core.hpp>
-#include <wpi/ArrayRef.h>
-#include <wpi/Twine.h>
#include "ConfigurableSourceImpl.h"
#include "SourceImpl.h"
@@ -25,7 +21,7 @@
class CvSourceImpl : public ConfigurableSourceImpl {
public:
- CvSourceImpl(const wpi::Twine& name, wpi::Logger& logger, Notifier& notifier,
+ CvSourceImpl(std::string_view name, wpi::Logger& logger, Notifier& notifier,
Telemetry& telemetry, const VideoMode& mode);
~CvSourceImpl() override;
diff --git a/cscore/src/main/native/cpp/Frame.cpp b/cscore/src/main/native/cpp/Frame.cpp
index 466cb52..0aa1947 100644
--- a/cscore/src/main/native/cpp/Frame.cpp
+++ b/cscore/src/main/native/cpp/Frame.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#include "Frame.h"
@@ -19,10 +16,10 @@
using namespace cs;
-Frame::Frame(SourceImpl& source, const wpi::Twine& error, Time time)
+Frame::Frame(SourceImpl& source, std::string_view error, Time time)
: m_impl{source.AllocFrameImpl().release()} {
m_impl->refcount = 1;
- m_impl->error = error.str();
+ m_impl->error = error;
m_impl->time = time;
}
@@ -35,22 +32,31 @@
}
Image* Frame::GetNearestImage(int width, int height) const {
- if (!m_impl) return nullptr;
+ if (!m_impl) {
+ return nullptr;
+ }
std::scoped_lock lock(m_impl->mutex);
Image* found = nullptr;
// Ideally we want the smallest image at least width/height in size
for (auto i : m_impl->images) {
- if (i->IsLarger(width, height) && (!found || (i->IsSmaller(*found))))
+ if (i->IsLarger(width, height) && (!found || (i->IsSmaller(*found)))) {
found = i;
+ }
}
- if (found) return found;
+ if (found) {
+ return found;
+ }
// Find the largest image (will be less than width/height)
for (auto i : m_impl->images) {
- if (!found || (i->IsLarger(*found))) found = i;
+ if (!found || (i->IsLarger(*found))) {
+ found = i;
+ }
}
- if (found) return found;
+ if (found) {
+ return found;
+ }
// Shouldn't reach this, but just in case...
return m_impl->images.empty() ? nullptr : m_impl->images[0];
@@ -59,7 +65,9 @@
Image* Frame::GetNearestImage(int width, int height,
VideoMode::PixelFormat pixelFormat,
int jpegQuality) const {
- if (!m_impl) return nullptr;
+ if (!m_impl) {
+ return nullptr;
+ }
std::scoped_lock lock(m_impl->mutex);
Image* found = nullptr;
@@ -74,19 +82,25 @@
// 1) Same width, height, pixelFormat, and (possibly) JPEG quality
// (e.g. exactly what we want)
for (auto i : m_impl->images) {
- if (i->Is(width, height, pixelFormat, jpegQuality)) return i;
+ if (i->Is(width, height, pixelFormat, jpegQuality)) {
+ return i;
+ }
}
// 2) Same width, height, different (but non-JPEG) pixelFormat (color conv)
// 2a) If we want JPEG output, prefer BGR over other pixel formats
if (pixelFormat == VideoMode::kMJPEG) {
for (auto i : m_impl->images) {
- if (i->Is(width, height, VideoMode::kBGR)) return i;
+ if (i->Is(width, height, VideoMode::kBGR)) {
+ return i;
+ }
}
}
for (auto i : m_impl->images) {
- if (i->Is(width, height) && i->pixelFormat != VideoMode::kMJPEG) return i;
+ if (i->Is(width, height) && i->pixelFormat != VideoMode::kMJPEG) {
+ return i;
+ }
}
// 3) Different width, height, same pixelFormat (only if non-JPEG) (resample)
@@ -94,17 +108,23 @@
// 3a) Smallest image at least width/height in size
for (auto i : m_impl->images) {
if (i->IsLarger(width, height) && i->pixelFormat == pixelFormat &&
- (!found || (i->IsSmaller(*found))))
+ (!found || (i->IsSmaller(*found)))) {
found = i;
+ }
}
- if (found) return found;
+ if (found) {
+ return found;
+ }
// 3b) Largest image (less than width/height)
for (auto i : m_impl->images) {
- if (i->pixelFormat == pixelFormat && (!found || (i->IsLarger(*found))))
+ if (i->pixelFormat == pixelFormat && (!found || (i->IsLarger(*found)))) {
found = i;
+ }
}
- if (found) return found;
+ if (found) {
+ return found;
+ }
}
// 4) Different width, height, different (but non-JPEG) pixelFormat
@@ -112,18 +132,24 @@
// 4a) Smallest image at least width/height in size
for (auto i : m_impl->images) {
if (i->IsLarger(width, height) && i->pixelFormat != VideoMode::kMJPEG &&
- (!found || (i->IsSmaller(*found))))
+ (!found || (i->IsSmaller(*found)))) {
found = i;
+ }
}
- if (found) return found;
+ if (found) {
+ return found;
+ }
// 4b) Largest image (less than width/height)
for (auto i : m_impl->images) {
if (i->pixelFormat != VideoMode::kMJPEG &&
- (!found || (i->IsLarger(*found))))
+ (!found || (i->IsLarger(*found)))) {
found = i;
+ }
}
- if (found) return found;
+ if (found) {
+ return found;
+ }
// 5) Same width, height, JPEG pixelFormat (decompression). As there may be
// multiple JPEG images, find the highest quality one.
@@ -133,27 +159,37 @@
found = i;
// consider one without a quality setting to be the highest quality
// (e.g. directly from the camera)
- if (i->jpegQuality == -1) break;
+ if (i->jpegQuality == -1) {
+ break;
+ }
}
}
- if (found) return found;
+ if (found) {
+ return found;
+ }
// 6) Different width, height, JPEG pixelFormat (decompression)
// 6a) Smallest image at least width/height in size
for (auto i : m_impl->images) {
if (i->IsLarger(width, height) && i->pixelFormat == VideoMode::kMJPEG &&
- (!found || (i->IsSmaller(*found))))
+ (!found || (i->IsSmaller(*found)))) {
found = i;
+ }
}
- if (found) return found;
+ if (found) {
+ return found;
+ }
// 6b) Largest image (less than width/height)
for (auto i : m_impl->images) {
if (i->pixelFormat != VideoMode::kMJPEG &&
- (!found || (i->IsLarger(*found))))
+ (!found || (i->IsLarger(*found)))) {
found = i;
+ }
}
- if (found) return found;
+ if (found) {
+ return found;
+ }
// Shouldn't reach this, but just in case...
return m_impl->images.empty() ? nullptr : m_impl->images[0];
@@ -161,9 +197,10 @@
Image* Frame::ConvertImpl(Image* image, VideoMode::PixelFormat pixelFormat,
int requiredJpegQuality, int defaultJpegQuality) {
- if (!image ||
- image->Is(image->width, image->height, pixelFormat, requiredJpegQuality))
+ if (!image || image->Is(image->width, image->height, pixelFormat,
+ requiredJpegQuality)) {
return image;
+ }
Image* cur = image;
// If the source image is a JPEG, we need to decode it before we can do
@@ -172,7 +209,9 @@
// would have returned above).
if (cur->pixelFormat == VideoMode::kMJPEG) {
cur = ConvertMJPEGToBGR(cur);
- if (pixelFormat == VideoMode::kBGR) return cur;
+ if (pixelFormat == VideoMode::kBGR) {
+ return cur;
+ }
}
// Color convert
@@ -182,17 +221,19 @@
if (cur->pixelFormat == VideoMode::kYUYV) {
// Check to see if BGR version already exists...
if (Image* newImage =
- GetExistingImage(cur->width, cur->height, VideoMode::kBGR))
+ GetExistingImage(cur->width, cur->height, VideoMode::kBGR)) {
cur = newImage;
- else
+ } else {
cur = ConvertYUYVToBGR(cur);
+ }
} else if (cur->pixelFormat == VideoMode::kGray) {
// Check to see if BGR version already exists...
if (Image* newImage =
- GetExistingImage(cur->width, cur->height, VideoMode::kBGR))
+ GetExistingImage(cur->width, cur->height, VideoMode::kBGR)) {
cur = newImage;
- else
+ } else {
cur = ConvertGrayToBGR(cur);
+ }
}
return ConvertBGRToRGB565(cur);
case VideoMode::kGray:
@@ -200,17 +241,19 @@
if (cur->pixelFormat == VideoMode::kYUYV) {
// Check to see if BGR version already exists...
if (Image* newImage =
- GetExistingImage(cur->width, cur->height, VideoMode::kBGR))
+ GetExistingImage(cur->width, cur->height, VideoMode::kBGR)) {
cur = newImage;
- else
+ } else {
cur = ConvertYUYVToBGR(cur);
+ }
} else if (cur->pixelFormat == VideoMode::kRGB565) {
// Check to see if BGR version already exists...
if (Image* newImage =
- GetExistingImage(cur->width, cur->height, VideoMode::kBGR))
+ GetExistingImage(cur->width, cur->height, VideoMode::kBGR)) {
cur = newImage;
- else
+ } else {
cur = ConvertRGB565ToBGR(cur);
+ }
}
return ConvertBGRToGray(cur);
case VideoMode::kBGR:
@@ -220,10 +263,11 @@
} else if (cur->pixelFormat == VideoMode::kRGB565) {
cur = ConvertRGB565ToBGR(cur);
} else if (cur->pixelFormat == VideoMode::kGray) {
- if (pixelFormat == VideoMode::kBGR)
+ if (pixelFormat == VideoMode::kBGR) {
return ConvertGrayToBGR(cur);
- else
+ } else {
return ConvertGrayToMJPEG(cur, defaultJpegQuality);
+ }
}
break;
case VideoMode::kYUYV:
@@ -232,14 +276,17 @@
}
// Compress if destination is JPEG
- if (pixelFormat == VideoMode::kMJPEG)
+ if (pixelFormat == VideoMode::kMJPEG) {
cur = ConvertBGRToMJPEG(cur, defaultJpegQuality);
+ }
return cur;
}
Image* Frame::ConvertMJPEGToBGR(Image* image) {
- if (!image || image->pixelFormat != VideoMode::kMJPEG) return nullptr;
+ if (!image || image->pixelFormat != VideoMode::kMJPEG) {
+ return nullptr;
+ }
// Allocate an BGR image
auto newImage =
@@ -260,7 +307,9 @@
}
Image* Frame::ConvertMJPEGToGray(Image* image) {
- if (!image || image->pixelFormat != VideoMode::kMJPEG) return nullptr;
+ if (!image || image->pixelFormat != VideoMode::kMJPEG) {
+ return nullptr;
+ }
// Allocate an grayscale image
auto newImage =
@@ -281,7 +330,9 @@
}
Image* Frame::ConvertYUYVToBGR(Image* image) {
- if (!image || image->pixelFormat != VideoMode::kYUYV) return nullptr;
+ if (!image || image->pixelFormat != VideoMode::kYUYV) {
+ return nullptr;
+ }
// Allocate a BGR image
auto newImage =
@@ -301,7 +352,9 @@
}
Image* Frame::ConvertBGRToRGB565(Image* image) {
- if (!image || image->pixelFormat != VideoMode::kBGR) return nullptr;
+ if (!image || image->pixelFormat != VideoMode::kBGR) {
+ return nullptr;
+ }
// Allocate a RGB565 image
auto newImage =
@@ -321,7 +374,9 @@
}
Image* Frame::ConvertRGB565ToBGR(Image* image) {
- if (!image || image->pixelFormat != VideoMode::kRGB565) return nullptr;
+ if (!image || image->pixelFormat != VideoMode::kRGB565) {
+ return nullptr;
+ }
// Allocate a BGR image
auto newImage =
@@ -341,7 +396,9 @@
}
Image* Frame::ConvertBGRToGray(Image* image) {
- if (!image || image->pixelFormat != VideoMode::kBGR) return nullptr;
+ if (!image || image->pixelFormat != VideoMode::kBGR) {
+ return nullptr;
+ }
// Allocate a Grayscale image
auto newImage =
@@ -361,7 +418,9 @@
}
Image* Frame::ConvertGrayToBGR(Image* image) {
- if (!image || image->pixelFormat != VideoMode::kGray) return nullptr;
+ if (!image || image->pixelFormat != VideoMode::kGray) {
+ return nullptr;
+ }
// Allocate a BGR image
auto newImage =
@@ -381,8 +440,12 @@
}
Image* Frame::ConvertBGRToMJPEG(Image* image, int quality) {
- if (!image || image->pixelFormat != VideoMode::kBGR) return nullptr;
- if (!m_impl) return nullptr;
+ if (!image || image->pixelFormat != VideoMode::kBGR) {
+ return nullptr;
+ }
+ if (!m_impl) {
+ return nullptr;
+ }
std::scoped_lock lock(m_impl->mutex);
// Allocate a JPEG image. We don't actually know what the resulting size
@@ -412,8 +475,12 @@
}
Image* Frame::ConvertGrayToMJPEG(Image* image, int quality) {
- if (!image || image->pixelFormat != VideoMode::kGray) return nullptr;
- if (!m_impl) return nullptr;
+ if (!image || image->pixelFormat != VideoMode::kGray) {
+ return nullptr;
+ }
+ if (!m_impl) {
+ return nullptr;
+ }
std::scoped_lock lock(m_impl->mutex);
// Allocate a JPEG image. We don't actually know what the resulting size
@@ -445,23 +512,26 @@
Image* Frame::GetImageImpl(int width, int height,
VideoMode::PixelFormat pixelFormat,
int requiredJpegQuality, int defaultJpegQuality) {
- if (!m_impl) return nullptr;
+ if (!m_impl) {
+ return nullptr;
+ }
std::scoped_lock lock(m_impl->mutex);
Image* cur = GetNearestImage(width, height, pixelFormat, requiredJpegQuality);
- if (!cur || cur->Is(width, height, pixelFormat, requiredJpegQuality))
+ if (!cur || cur->Is(width, height, pixelFormat, requiredJpegQuality)) {
return cur;
+ }
WPI_DEBUG4(Instance::GetInstance().logger,
- "converting image from " << cur->width << "x" << cur->height
- << " type " << cur->pixelFormat << " to "
- << width << "x" << height << " type "
- << pixelFormat);
+ "converting image from {}x{} type {} to {}x{} type {}", cur->width,
+ cur->height, cur->pixelFormat, width, height, pixelFormat);
// If the source image is a JPEG, we need to decode it before we can do
// anything else with it. Note that if the destination format is JPEG, we
// still need to do this (unless the width/height/compression were the same,
// in which case we already returned the existing JPEG above).
- if (cur->pixelFormat == VideoMode::kMJPEG) cur = ConvertMJPEGToBGR(cur);
+ if (cur->pixelFormat == VideoMode::kMJPEG) {
+ cur = ConvertMJPEGToBGR(cur);
+ }
// Resize
if (!cur->Is(width, height)) {
@@ -485,14 +555,17 @@
bool Frame::GetCv(cv::Mat& image, int width, int height) {
Image* rawImage = GetImage(width, height, VideoMode::kBGR);
- if (!rawImage) return false;
+ if (!rawImage) {
+ return false;
+ }
rawImage->AsMat().copyTo(image);
return true;
}
void Frame::ReleaseFrame() {
- for (auto image : m_impl->images)
+ for (auto image : m_impl->images) {
m_impl->source.ReleaseImage(std::unique_ptr<Image>(image));
+ }
m_impl->images.clear();
m_impl->source.ReleaseFrameImpl(std::unique_ptr<Impl>(m_impl));
m_impl = nullptr;
diff --git a/cscore/src/main/native/cpp/Frame.h b/cscore/src/main/native/cpp/Frame.h
index 07fa24f..9a16824 100644
--- a/cscore/src/main/native/cpp/Frame.h
+++ b/cscore/src/main/native/cpp/Frame.h
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#ifndef CSCORE_FRAME_H_
#define CSCORE_FRAME_H_
@@ -11,11 +8,11 @@
#include <atomic>
#include <memory>
#include <string>
+#include <string_view>
#include <utility>
#include <vector>
#include <wpi/SmallVector.h>
-#include <wpi/Twine.h>
#include <wpi/mutex.h>
#include "Image.h"
@@ -45,14 +42,16 @@
};
public:
- Frame() noexcept : m_impl{nullptr} {}
+ Frame() noexcept = default;
- Frame(SourceImpl& source, const wpi::Twine& error, Time time);
+ Frame(SourceImpl& source, std::string_view error, Time time);
Frame(SourceImpl& source, std::unique_ptr<Image> image, Time time);
Frame(const Frame& frame) noexcept : m_impl{frame.m_impl} {
- if (m_impl) ++m_impl->refcount;
+ if (m_impl) {
+ ++m_impl->refcount;
+ }
}
Frame(Frame&& other) noexcept : Frame() { swap(*this, other); }
@@ -73,61 +72,91 @@
Time GetTime() const { return m_impl ? m_impl->time : 0; }
- wpi::StringRef GetError() const {
- if (!m_impl) return wpi::StringRef{};
+ std::string_view GetError() const {
+ if (!m_impl) {
+ return {};
+ }
return m_impl->error;
}
int GetOriginalWidth() const {
- if (!m_impl) return 0;
+ if (!m_impl) {
+ return 0;
+ }
std::scoped_lock lock(m_impl->mutex);
- if (m_impl->images.empty()) return 0;
+ if (m_impl->images.empty()) {
+ return 0;
+ }
return m_impl->images[0]->width;
}
int GetOriginalHeight() const {
- if (!m_impl) return 0;
+ if (!m_impl) {
+ return 0;
+ }
std::scoped_lock lock(m_impl->mutex);
- if (m_impl->images.empty()) return 0;
+ if (m_impl->images.empty()) {
+ return 0;
+ }
return m_impl->images[0]->height;
}
int GetOriginalPixelFormat() const {
- if (!m_impl) return 0;
+ if (!m_impl) {
+ return 0;
+ }
std::scoped_lock lock(m_impl->mutex);
- if (m_impl->images.empty()) return 0;
+ if (m_impl->images.empty()) {
+ return 0;
+ }
return m_impl->images[0]->pixelFormat;
}
int GetOriginalJpegQuality() const {
- if (!m_impl) return 0;
+ if (!m_impl) {
+ return 0;
+ }
std::scoped_lock lock(m_impl->mutex);
- if (m_impl->images.empty()) return 0;
+ 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;
+ if (!m_impl) {
+ return nullptr;
+ }
std::scoped_lock lock(m_impl->mutex);
- if (i >= m_impl->images.size()) return nullptr;
+ 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;
+ if (!m_impl) {
+ return nullptr;
+ }
std::scoped_lock lock(m_impl->mutex);
for (auto i : m_impl->images) {
- if (i->Is(width, height)) return i;
+ if (i->Is(width, height)) {
+ return i;
+ }
}
return nullptr;
}
Image* GetExistingImage(int width, int height,
VideoMode::PixelFormat pixelFormat) const {
- if (!m_impl) return nullptr;
+ if (!m_impl) {
+ return nullptr;
+ }
std::scoped_lock lock(m_impl->mutex);
for (auto i : m_impl->images) {
- if (i->Is(width, height, pixelFormat)) return i;
+ if (i->Is(width, height, pixelFormat)) {
+ return i;
+ }
}
return nullptr;
}
@@ -135,10 +164,14 @@
Image* GetExistingImage(int width, int height,
VideoMode::PixelFormat pixelFormat,
int jpegQuality) const {
- if (!m_impl) return nullptr;
+ if (!m_impl) {
+ return nullptr;
+ }
std::scoped_lock lock(m_impl->mutex);
for (auto i : m_impl->images) {
- if (i->Is(width, height, pixelFormat, jpegQuality)) return i;
+ if (i->Is(width, height, pixelFormat, jpegQuality)) {
+ return i;
+ }
}
return nullptr;
}
@@ -149,7 +182,9 @@
int jpegQuality = -1) const;
Image* Convert(Image* image, VideoMode::PixelFormat pixelFormat) {
- if (pixelFormat == VideoMode::kMJPEG) return nullptr;
+ if (pixelFormat == VideoMode::kMJPEG) {
+ return nullptr;
+ }
return ConvertImpl(image, pixelFormat, -1, 80);
}
Image* ConvertToMJPEG(Image* image, int requiredQuality,
@@ -168,7 +203,9 @@
Image* ConvertGrayToMJPEG(Image* image, int quality);
Image* GetImage(int width, int height, VideoMode::PixelFormat pixelFormat) {
- if (pixelFormat == VideoMode::kMJPEG) return nullptr;
+ if (pixelFormat == VideoMode::kMJPEG) {
+ return nullptr;
+ }
return GetImageImpl(width, height, pixelFormat, -1, 80);
}
Image* GetImageMJPEG(int width, int height, int requiredQuality,
@@ -188,11 +225,13 @@
Image* GetImageImpl(int width, int height, VideoMode::PixelFormat pixelFormat,
int requiredJpegQuality, int defaultJpegQuality);
void DecRef() {
- if (m_impl && --(m_impl->refcount) == 0) ReleaseFrame();
+ if (m_impl && --(m_impl->refcount) == 0) {
+ ReleaseFrame();
+ }
}
void ReleaseFrame();
- Impl* m_impl;
+ Impl* m_impl{nullptr};
};
} // namespace cs
diff --git a/cscore/src/main/native/cpp/Handle.h b/cscore/src/main/native/cpp/Handle.h
index ebb3a55..91df0eb 100644
--- a/cscore/src/main/native/cpp/Handle.h
+++ b/cscore/src/main/native/cpp/Handle.h
@@ -1,13 +1,12 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2018 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#ifndef CSCORE_HANDLE_H_
#define CSCORE_HANDLE_H_
+#include <wpi/Synchronization.h>
+
#include "cscore_c.h"
namespace cs {
@@ -21,11 +20,12 @@
public:
enum Type {
kUndefined = 0,
- kProperty = 0x40,
+ kProperty = wpi::kHandleTypeCSBase,
kSource,
kSink,
kListener,
- kSinkProperty
+ kSinkProperty,
+ kListenerPoller
};
enum { kIndexMax = 0xffff };
diff --git a/cscore/src/main/native/cpp/HttpCameraImpl.cpp b/cscore/src/main/native/cpp/HttpCameraImpl.cpp
index 57c86a8..068393b 100644
--- a/cscore/src/main/native/cpp/HttpCameraImpl.cpp
+++ b/cscore/src/main/native/cpp/HttpCameraImpl.cpp
@@ -1,13 +1,11 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#include "HttpCameraImpl.h"
#include <wpi/MemAlloc.h>
+#include <wpi/StringExtras.h>
#include <wpi/TCPConnector.h>
#include <wpi/timestamp.h>
@@ -21,7 +19,7 @@
using namespace cs;
-HttpCameraImpl::HttpCameraImpl(const wpi::Twine& name, CS_HttpCameraKind kind,
+HttpCameraImpl::HttpCameraImpl(std::string_view name, CS_HttpCameraKind kind,
wpi::Logger& logger, Notifier& notifier,
Telemetry& telemetry)
: SourceImpl{name, logger, notifier, telemetry}, m_kind{kind} {}
@@ -33,26 +31,36 @@
m_monitorCond.notify_one();
// join monitor thread
- if (m_monitorThread.joinable()) m_monitorThread.join();
+ if (m_monitorThread.joinable()) {
+ m_monitorThread.join();
+ }
// Close file if it's open
{
std::scoped_lock lock(m_mutex);
- if (m_streamConn) m_streamConn->stream->close();
- if (m_settingsConn) m_settingsConn->stream->close();
+ if (m_streamConn) {
+ m_streamConn->stream->close();
+ }
+ if (m_settingsConn) {
+ m_settingsConn->stream->close();
+ }
}
// force wakeup of camera thread in case it's waiting on cv
m_sinkEnabledCond.notify_one();
// join camera thread
- if (m_streamThread.joinable()) m_streamThread.join();
+ if (m_streamThread.joinable()) {
+ m_streamThread.join();
+ }
// force wakeup of settings thread
m_settingsCond.notify_one();
// join settings thread
- if (m_settingsThread.joinable()) m_settingsThread.join();
+ if (m_settingsThread.joinable()) {
+ m_settingsThread.join();
+ }
}
void HttpCameraImpl::Start() {
@@ -69,13 +77,15 @@
m_monitorCond.wait_for(lock, std::chrono::seconds(1),
[=] { return !m_active; });
- if (!m_active) break;
+ if (!m_active) {
+ break;
+ }
// check to see if we got any frames, and close the stream if not
// (this will result in an error at the read point, and ultimately
// a reconnect attempt)
if (m_streamConn && m_frameCount == 0) {
- SWARNING("Monitor detected stream hung, disconnecting");
+ SWARNING("{}", "Monitor detected stream hung, disconnecting");
m_streamConn->stream->close();
}
@@ -83,7 +93,7 @@
m_frameCount = 0;
}
- SDEBUG("Monitor Thread exiting");
+ SDEBUG("{}", "Monitor Thread exiting");
}
void HttpCameraImpl::StreamThreadMain() {
@@ -96,33 +106,41 @@
// disconnect if not enabled
if (!IsEnabled()) {
std::unique_lock lock(m_mutex);
- if (m_streamConn) m_streamConn->stream->close();
+ if (m_streamConn) {
+ m_streamConn->stream->close();
+ }
// Wait for enable
m_sinkEnabledCond.wait(lock, [=] { return !m_active || IsEnabled(); });
- if (!m_active) return;
+ if (!m_active) {
+ return;
+ }
}
// connect
wpi::SmallString<64> boundary;
wpi::HttpConnection* conn = DeviceStreamConnect(boundary);
- if (!m_active) break;
+ if (!m_active) {
+ break;
+ }
// keep retrying
- if (!conn) continue;
+ if (!conn) {
+ continue;
+ }
// update connected since we're actually connected
SetConnected(true);
// stream
- DeviceStream(conn->is, boundary);
+ DeviceStream(conn->is, boundary.str());
{
std::unique_lock lock(m_mutex);
m_streamConn = nullptr;
}
}
- SDEBUG("Camera Thread exiting");
+ SDEBUG("{}", "Camera Thread exiting");
SetConnected(false);
}
@@ -133,11 +151,13 @@
{
std::scoped_lock lock(m_mutex);
if (m_locations.empty()) {
- SERROR("locations array is empty!?");
+ SERROR("{}", "locations array is empty!?");
std::this_thread::sleep_for(std::chrono::seconds(1));
return nullptr;
}
- if (m_nextLocation >= m_locations.size()) m_nextLocation = 0;
+ if (m_nextLocation >= m_locations.size()) {
+ m_nextLocation = 0;
+ }
req = wpi::HttpRequest{m_locations[m_nextLocation++], m_streamSettings};
m_streamSettingsUpdated = false;
}
@@ -146,7 +166,9 @@
auto stream =
wpi::TCPConnector::connect(req.host.c_str(), req.port, m_logger, 1);
- if (!m_active || !stream) return nullptr;
+ if (!m_active || !stream) {
+ return nullptr;
+ }
auto connPtr = std::make_unique<wpi::HttpConnection>(std::move(stream), 1);
wpi::HttpConnection* conn = connPtr.get();
@@ -160,19 +182,17 @@
std::string warn;
if (!conn->Handshake(req, &warn)) {
- SWARNING(GetName() << ": " << warn);
+ SWARNING("{}", warn);
std::scoped_lock lock(m_mutex);
m_streamConn = nullptr;
return nullptr;
}
// Parse Content-Type header to get the boundary
- wpi::StringRef mediaType, contentType;
- std::tie(mediaType, contentType) = conn->contentType.str().split(';');
- mediaType = mediaType.trim();
+ auto [mediaType, contentType] = wpi::split(conn->contentType.str(), ';');
+ mediaType = wpi::trim(mediaType);
if (mediaType != "multipart/x-mixed-replace") {
- SWARNING("\"" << req.host << "\": unrecognized Content-Type \"" << mediaType
- << "\"");
+ SWARNING("\"{}\": unrecognized Content-Type \"{}\"", req.host, mediaType);
std::scoped_lock lock(m_mutex);
m_streamConn = nullptr;
return nullptr;
@@ -181,14 +201,13 @@
// media parameters
boundary.clear();
while (!contentType.empty()) {
- wpi::StringRef keyvalue;
- std::tie(keyvalue, contentType) = contentType.split(';');
- contentType = contentType.ltrim();
- wpi::StringRef key, value;
- std::tie(key, value) = keyvalue.split('=');
- if (key.trim() == "boundary") {
- value = value.trim().trim('"'); // value may be quoted
- if (value.startswith("--")) {
+ std::string_view keyvalue;
+ std::tie(keyvalue, contentType) = wpi::split(contentType, ';');
+ contentType = wpi::ltrim(contentType);
+ auto [key, value] = wpi::split(keyvalue, '=');
+ if (wpi::trim(key) == "boundary") {
+ value = wpi::trim(wpi::trim(value), '"'); // value may be quoted
+ if (wpi::starts_with(value, "--")) {
value = value.substr(2);
}
boundary.append(value.begin(), value.end());
@@ -196,8 +215,7 @@
}
if (boundary.empty()) {
- SWARNING("\"" << req.host
- << "\": empty multi-part boundary or no Content-Type");
+ SWARNING("\"{}\": empty multi-part boundary or no Content-Type", req.host);
std::scoped_lock lock(m_mutex);
m_streamConn = nullptr;
return nullptr;
@@ -207,7 +225,7 @@
}
void HttpCameraImpl::DeviceStream(wpi::raw_istream& is,
- wpi::StringRef boundary) {
+ std::string_view boundary) {
// Stored here so we reuse it from frame to frame
std::string imageBuf;
@@ -218,24 +236,33 @@
// streaming loop
while (m_active && !is.has_error() && IsEnabled() && numErrors < 3 &&
!m_streamSettingsUpdated) {
- if (!FindMultipartBoundary(is, boundary, nullptr)) break;
+ 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, 1);
- if (!m_active || is.has_error()) break;
+ if (!m_active || is.has_error()) {
+ break;
+ }
if (eol[0] != '\n') {
is.read(eol + 1, 1);
- if (!m_active || is.has_error()) break;
+ if (!m_active || is.has_error()) {
+ break;
+ }
// End-of-stream is indicated with trailing --
- if (eol[0] == '-' && eol[1] == '-') break;
+ if (eol[0] == '-' && eol[1] == '-') {
+ break;
+ }
}
- if (!DeviceStreamFrame(is, imageBuf))
+ if (!DeviceStreamFrame(is, imageBuf)) {
++numErrors;
- else
+ } else {
numErrors = 0;
+ }
}
}
@@ -245,28 +272,29 @@
wpi::SmallString<64> contentTypeBuf;
wpi::SmallString<64> contentLengthBuf;
if (!ParseHttpHeaders(is, &contentTypeBuf, &contentLengthBuf)) {
- SWARNING("disconnected during headers");
+ SWARNING("{}", "disconnected during headers");
PutError("disconnected during headers", wpi::Now());
return false;
}
// Check the content type (if present)
if (!contentTypeBuf.str().empty() &&
- !contentTypeBuf.str().startswith("image/jpeg")) {
- wpi::SmallString<64> errBuf;
- wpi::raw_svector_ostream errMsg{errBuf};
- errMsg << "received unknown Content-Type \"" << contentTypeBuf << "\"";
- SWARNING(errMsg.str());
- PutError(errMsg.str(), wpi::Now());
+ !wpi::starts_with(contentTypeBuf, "image/jpeg")) {
+ auto errMsg =
+ fmt::format("received unknown Content-Type \"{}\"", contentTypeBuf);
+ SWARNING("{}", errMsg);
+ PutError(errMsg, wpi::Now());
return false;
}
unsigned int contentLength = 0;
- if (contentLengthBuf.str().getAsInteger(10, contentLength)) {
+ if (auto v = wpi::parse_integer<unsigned int>(contentLengthBuf, 10)) {
+ contentLength = v.value();
+ } else {
// Ugh, no Content-Length? Read the blocks of the JPEG file.
int width, height;
if (!ReadJpeg(is, imageBuf, &width, &height)) {
- SWARNING("did not receive a JPEG image");
+ SWARNING("{}", "did not receive a JPEG image");
PutError("did not receive a JPEG image", wpi::Now());
return false;
}
@@ -280,10 +308,12 @@
// the data directly into it.
auto image = AllocImage(VideoMode::PixelFormat::kMJPEG, 0, 0, contentLength);
is.read(image->data(), contentLength);
- if (!m_active || is.has_error()) return false;
+ if (!m_active || is.has_error()) {
+ return false;
+ }
int width, height;
if (!GetJpegSize(image->str(), &width, &height)) {
- SWARNING("did not receive a JPEG image");
+ SWARNING("{}", "did not receive a JPEG image");
PutError("did not receive a JPEG image", wpi::Now());
return false;
}
@@ -302,7 +332,9 @@
m_settingsCond.wait(lock, [=] {
return !m_active || (m_prefLocation != -1 && !m_settings.empty());
});
- if (!m_active) break;
+ if (!m_active) {
+ break;
+ }
// Build the request
req = wpi::HttpRequest{m_locations[m_prefLocation], m_settings};
@@ -311,7 +343,7 @@
DeviceSendSettings(req);
}
- SDEBUG("Settings Thread exiting");
+ SDEBUG("{}", "Settings Thread exiting");
}
void HttpCameraImpl::DeviceSendSettings(wpi::HttpRequest& req) {
@@ -319,7 +351,9 @@
auto stream =
wpi::TCPConnector::connect(req.host.c_str(), req.port, m_logger, 1);
- if (!m_active || !stream) return;
+ if (!m_active || !stream) {
+ return;
+ }
auto connPtr = std::make_unique<wpi::HttpConnection>(std::move(stream), 1);
wpi::HttpConnection* conn = connPtr.get();
@@ -332,7 +366,9 @@
// Just need a handshake as settings are sent via GET parameters
std::string warn;
- if (!conn->Handshake(req, &warn)) SWARNING(GetName() << ": " << warn);
+ if (!conn->Handshake(req, &warn)) {
+ SWARNING("{}", warn);
+ }
conn->stream->close();
}
@@ -342,7 +378,7 @@
return m_kind;
}
-bool HttpCameraImpl::SetUrls(wpi::ArrayRef<std::string> urls,
+bool HttpCameraImpl::SetUrls(wpi::span<const std::string> urls,
CS_Status* status) {
std::vector<wpi::HttpLocation> locations;
for (const auto& url : urls) {
@@ -350,7 +386,7 @@
std::string errorMsg;
locations.emplace_back(url, &error, &errorMsg);
if (error) {
- SERROR(GetName() << ": " << errorMsg);
+ SERROR("{}", errorMsg);
*status = CS_BAD_URL;
return false;
}
@@ -366,12 +402,14 @@
std::vector<std::string> HttpCameraImpl::GetUrls() const {
std::scoped_lock lock(m_mutex);
std::vector<std::string> urls;
- for (const auto& loc : m_locations) urls.push_back(loc.url);
+ for (const auto& loc : m_locations) {
+ urls.push_back(loc.url);
+ }
return urls;
}
-void HttpCameraImpl::CreateProperty(const wpi::Twine& name,
- const wpi::Twine& httpParam,
+void HttpCameraImpl::CreateProperty(std::string_view name,
+ std::string_view httpParam,
bool viaSettings, CS_PropertyKind kind,
int minimum, int maximum, int step,
int defaultValue, int value) const {
@@ -381,13 +419,12 @@
value));
m_notifier.NotifySourceProperty(*this, CS_SOURCE_PROPERTY_CREATED, name,
- m_propertyData.size() + 1, kind, value,
- wpi::Twine{});
+ m_propertyData.size() + 1, kind, value, {});
}
template <typename T>
void HttpCameraImpl::CreateEnumProperty(
- const wpi::Twine& name, const wpi::Twine& httpParam, bool viaSettings,
+ std::string_view name, std::string_view httpParam, bool viaSettings,
int defaultValue, int value, std::initializer_list<T> choices) const {
std::scoped_lock lock(m_mutex);
m_propertyData.emplace_back(std::make_unique<PropertyData>(
@@ -396,18 +433,20 @@
auto& enumChoices = m_propertyData.back()->enumChoices;
enumChoices.clear();
- for (const auto& choice : choices) enumChoices.emplace_back(choice);
+ for (const auto& choice : choices) {
+ enumChoices.emplace_back(choice);
+ }
m_notifier.NotifySourceProperty(*this, CS_SOURCE_PROPERTY_CREATED, name,
m_propertyData.size() + 1, CS_PROP_ENUM,
- value, wpi::Twine{});
+ value, {});
m_notifier.NotifySourceProperty(*this, CS_SOURCE_PROPERTY_CHOICES_UPDATED,
name, m_propertyData.size() + 1, CS_PROP_ENUM,
- value, wpi::Twine{});
+ value, {});
}
std::unique_ptr<PropertyImpl> HttpCameraImpl::CreateEmptyProperty(
- const wpi::Twine& name) const {
+ std::string_view name) const {
return std::make_unique<PropertyData>(name);
}
@@ -432,7 +471,7 @@
// TODO
}
-void HttpCameraImpl::SetStringProperty(int property, const wpi::Twine& value,
+void HttpCameraImpl::SetStringProperty(int property, std::string_view value,
CS_Status* status) {
// TODO
}
@@ -471,7 +510,9 @@
}
bool HttpCameraImpl::SetVideoMode(const VideoMode& mode, CS_Status* status) {
- if (mode.pixelFormat != VideoMode::kMJPEG) return false;
+ if (mode.pixelFormat != VideoMode::kMJPEG) {
+ return false;
+ }
std::scoped_lock lock(m_mutex);
m_mode = mode;
m_streamSettingsUpdated = true;
@@ -516,7 +557,7 @@
namespace cs {
-CS_Source CreateHttpCamera(const wpi::Twine& name, const wpi::Twine& url,
+CS_Source CreateHttpCamera(std::string_view name, std::string_view url,
CS_HttpCameraKind kind, CS_Status* status) {
auto& inst = Instance::GetInstance();
std::shared_ptr<HttpCameraImpl> source;
@@ -530,12 +571,15 @@
inst.notifier, inst.telemetry);
break;
}
- if (!source->SetUrls(url.str(), status)) return 0;
+ std::string urlStr{url};
+ if (!source->SetUrls(wpi::span{&urlStr, 1}, status)) {
+ return 0;
+ }
return inst.CreateSource(CS_SOURCE_HTTP, source);
}
-CS_Source CreateHttpCamera(const wpi::Twine& name,
- wpi::ArrayRef<std::string> urls,
+CS_Source CreateHttpCamera(std::string_view name,
+ wpi::span<const std::string> urls,
CS_HttpCameraKind kind, CS_Status* status) {
auto& inst = Instance::GetInstance();
if (urls.empty()) {
@@ -544,7 +588,9 @@
}
auto source = std::make_shared<HttpCameraImpl>(name, kind, inst.logger,
inst.notifier, inst.telemetry);
- if (!source->SetUrls(urls, status)) return 0;
+ if (!source->SetUrls(urls, status)) {
+ return 0;
+ }
return inst.CreateSource(CS_SOURCE_HTTP, source);
}
@@ -557,7 +603,7 @@
return static_cast<HttpCameraImpl&>(*data->source).GetKind();
}
-void SetHttpCameraUrls(CS_Source source, wpi::ArrayRef<std::string> urls,
+void SetHttpCameraUrls(CS_Source source, wpi::span<const std::string> urls,
CS_Status* status) {
if (urls.empty()) {
*status = CS_EMPTY_VALUE;
@@ -595,7 +641,9 @@
CS_Status* status) {
wpi::SmallVector<std::string, 4> vec;
vec.reserve(count);
- for (int i = 0; i < count; ++i) vec.push_back(urls[i]);
+ for (int i = 0; i < count; ++i) {
+ vec.push_back(urls[i]);
+ }
return cs::CreateHttpCamera(name, vec, kind, status);
}
@@ -607,7 +655,9 @@
CS_Status* status) {
wpi::SmallVector<std::string, 4> vec;
vec.reserve(count);
- for (int i = 0; i < count; ++i) vec.push_back(urls[i]);
+ for (int i = 0; i < count; ++i) {
+ vec.push_back(urls[i]);
+ }
cs::SetHttpCameraUrls(source, vec, status);
}
@@ -616,13 +666,19 @@
char** out =
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]);
+ for (size_t i = 0; i < urls.size(); ++i) {
+ out[i] = cs::ConvertToC(urls[i]);
+ }
return out;
}
void CS_FreeHttpCameraUrls(char** urls, int count) {
- if (!urls) return;
- for (int i = 0; i < count; ++i) std::free(urls[i]);
+ if (!urls) {
+ return;
+ }
+ for (int i = 0; i < count; ++i) {
+ std::free(urls[i]);
+ }
std::free(urls);
}
diff --git a/cscore/src/main/native/cpp/HttpCameraImpl.h b/cscore/src/main/native/cpp/HttpCameraImpl.h
index 5967015..2c58936 100644
--- a/cscore/src/main/native/cpp/HttpCameraImpl.h
+++ b/cscore/src/main/native/cpp/HttpCameraImpl.h
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2018 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#ifndef CSCORE_HTTPCAMERAIMPL_H_
#define CSCORE_HTTPCAMERAIMPL_H_
@@ -13,15 +10,16 @@
#include <initializer_list>
#include <memory>
#include <string>
+#include <string_view>
#include <thread>
#include <vector>
#include <wpi/HttpUtil.h>
#include <wpi/SmallString.h>
#include <wpi/StringMap.h>
-#include <wpi/Twine.h>
#include <wpi/condition_variable.h>
#include <wpi/raw_istream.h>
+#include <wpi/span.h>
#include "SourceImpl.h"
#include "cscore_cpp.h"
@@ -30,7 +28,7 @@
class HttpCameraImpl : public SourceImpl {
public:
- HttpCameraImpl(const wpi::Twine& name, CS_HttpCameraKind kind,
+ HttpCameraImpl(std::string_view name, CS_HttpCameraKind kind,
wpi::Logger& logger, Notifier& notifier, Telemetry& telemetry);
~HttpCameraImpl() override;
@@ -38,7 +36,7 @@
// Property functions
void SetProperty(int property, int value, CS_Status* status) override;
- void SetStringProperty(int property, const wpi::Twine& value,
+ void SetStringProperty(int property, std::string_view value,
CS_Status* status) override;
// Standard common camera properties
@@ -57,20 +55,20 @@
void NumSinksEnabledChanged() override;
CS_HttpCameraKind GetKind() const;
- bool SetUrls(wpi::ArrayRef<std::string> urls, CS_Status* status);
+ bool SetUrls(wpi::span<const std::string> urls, CS_Status* status);
std::vector<std::string> GetUrls() const;
// Property data
class PropertyData : public PropertyImpl {
public:
PropertyData() = default;
- explicit PropertyData(const wpi::Twine& name_) : PropertyImpl{name_} {}
- PropertyData(const wpi::Twine& name_, const wpi::Twine& httpParam_,
+ explicit PropertyData(std::string_view name_) : PropertyImpl{name_} {}
+ PropertyData(std::string_view name_, std::string_view httpParam_,
bool viaSettings_, CS_PropertyKind kind_, int minimum_,
int maximum_, int step_, int defaultValue_, int value_)
: PropertyImpl(name_, kind_, step_, defaultValue_, value_),
viaSettings(viaSettings_),
- httpParam(httpParam_.str()) {
+ httpParam(httpParam_) {
hasMinimum = true;
minimum = minimum_;
hasMaximum = true;
@@ -84,16 +82,16 @@
protected:
std::unique_ptr<PropertyImpl> CreateEmptyProperty(
- const wpi::Twine& name) const override;
+ std::string_view name) const override;
bool CacheProperties(CS_Status* status) const override;
- void CreateProperty(const wpi::Twine& name, const wpi::Twine& httpParam,
+ void CreateProperty(std::string_view name, std::string_view httpParam,
bool viaSettings, CS_PropertyKind kind, int minimum,
int maximum, int step, int defaultValue, int value) const;
template <typename T>
- void CreateEnumProperty(const wpi::Twine& name, const wpi::Twine& httpParam,
+ void CreateEnumProperty(std::string_view name, std::string_view httpParam,
bool viaSettings, int defaultValue, int value,
std::initializer_list<T> choices) const;
@@ -104,7 +102,7 @@
// Functions used by StreamThreadMain()
wpi::HttpConnection* DeviceStreamConnect(
wpi::SmallVectorImpl<char>& boundary);
- void DeviceStream(wpi::raw_istream& is, wpi::StringRef boundary);
+ void DeviceStream(wpi::raw_istream& is, std::string_view boundary);
bool DeviceStreamFrame(wpi::raw_istream& is, std::string& imageBuf);
// The camera settings thread
@@ -149,12 +147,12 @@
class AxisCameraImpl : public HttpCameraImpl {
public:
- AxisCameraImpl(const wpi::Twine& name, wpi::Logger& logger,
- Notifier& notifier, Telemetry& telemetry)
+ AxisCameraImpl(std::string_view name, wpi::Logger& logger, Notifier& notifier,
+ Telemetry& telemetry)
: HttpCameraImpl{name, CS_HTTP_AXIS, logger, notifier, telemetry} {}
#if 0
void SetProperty(int property, int value, CS_Status* status) override;
- void SetStringProperty(int property, const wpi::Twine& value,
+ void SetStringProperty(int property, std::string_view value,
CS_Status* status) override;
#endif
protected:
diff --git a/cscore/src/main/native/cpp/Image.h b/cscore/src/main/native/cpp/Image.h
index 6305d93..9a1579f 100644
--- a/cscore/src/main/native/cpp/Image.h
+++ b/cscore/src/main/native/cpp/Image.h
@@ -1,17 +1,14 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2018 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#ifndef CSCORE_IMAGE_H_
#define CSCORE_IMAGE_H_
+#include <string_view>
#include <vector>
#include <opencv2/core/core.hpp>
-#include <wpi/StringRef.h>
#include "cscore_cpp.h"
#include "default_init_allocator.h"
@@ -37,8 +34,8 @@
Image& operator=(const Image&) = delete;
// Getters
- operator wpi::StringRef() const { return str(); }
- wpi::StringRef str() const { return wpi::StringRef(data(), size()); }
+ operator std::string_view() const { return str(); } // NOLINT
+ std::string_view str() const { return {data(), size()}; }
size_t capacity() const { return m_data.capacity(); }
const char* data() const {
return reinterpret_cast<const char*>(m_data.data());
diff --git a/cscore/src/main/native/cpp/Instance.cpp b/cscore/src/main/native/cpp/Instance.cpp
index 8dd5c26..3b81f01 100644
--- a/cscore/src/main/native/cpp/Instance.cpp
+++ b/cscore/src/main/native/cpp/Instance.cpp
@@ -1,48 +1,45 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2018 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#include "Instance.h"
-#include <wpi/Path.h>
-#include <wpi/SmallString.h>
-#include <wpi/StringRef.h>
-#include <wpi/raw_ostream.h>
+#include <string_view>
+
+#include <fmt/format.h>
+#include <wpi/fs.h>
using namespace cs;
static void def_log_func(unsigned int level, const char* file,
unsigned int line, const char* msg) {
- wpi::SmallString<128> buf;
- wpi::raw_svector_ostream oss(buf);
if (level == 20) {
- oss << "CS: " << msg << '\n';
- wpi::errs() << oss.str();
+ fmt::print(stderr, "CS: {}\n", msg);
return;
}
- wpi::StringRef levelmsg;
- if (level >= 50)
- levelmsg = "CRITICAL: ";
- else if (level >= 40)
- levelmsg = "ERROR: ";
- else if (level >= 30)
- levelmsg = "WARNING: ";
- else
+ std::string_view levelmsg;
+ if (level >= 50) {
+ levelmsg = "CRITICAL";
+ } else if (level >= 40) {
+ levelmsg = "ERROR";
+ } else if (level >= 30) {
+ levelmsg = "WARNING";
+ } else {
return;
- oss << "CS: " << levelmsg << msg << " (" << wpi::sys::path::filename(file)
- << ':' << line << ")\n";
- wpi::errs() << oss.str();
+ }
+ fmt::print(stderr, "CS: {}: {} ({}:{})\n", levelmsg, msg,
+ fs::path{file}.filename().string(), line);
}
-Instance::Instance() : telemetry(notifier), networkListener(logger, notifier) {
+Instance::Instance()
+ : telemetry(notifier),
+ networkListener(logger, notifier),
+ usbCameraListener(logger, notifier) {
SetDefaultLogger();
}
-Instance::~Instance() {}
+Instance::~Instance() = default;
Instance& Instance::GetInstance() {
static Instance* inst = new Instance;
@@ -54,11 +51,14 @@
m_sinks.FreeAll();
m_sources.FreeAll();
networkListener.Stop();
+ usbCameraListener.Stop();
telemetry.Stop();
notifier.Stop();
}
-void Instance::SetDefaultLogger() { logger.SetLogger(def_log_func); }
+void Instance::SetDefaultLogger() {
+ logger.SetLogger(def_log_func);
+}
std::pair<CS_Source, std::shared_ptr<SourceData>> Instance::FindSource(
const SourceImpl& source) {
@@ -87,11 +87,13 @@
}
void Instance::DestroySource(CS_Source handle) {
- if (auto data = m_sources.Free(handle))
+ if (auto data = m_sources.Free(handle)) {
notifier.NotifySource(data->source->GetName(), handle, CS_SOURCE_DESTROYED);
+ }
}
void Instance::DestroySink(CS_Sink handle) {
- if (auto data = m_sinks.Free(handle))
+ if (auto data = m_sinks.Free(handle)) {
notifier.NotifySink(data->sink->GetName(), handle, CS_SINK_DESTROYED);
+ }
}
diff --git a/cscore/src/main/native/cpp/Instance.h b/cscore/src/main/native/cpp/Instance.h
index 0c566f3..f84eacf 100644
--- a/cscore/src/main/native/cpp/Instance.h
+++ b/cscore/src/main/native/cpp/Instance.h
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2018 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#ifndef CSCORE_INSTANCE_H_
#define CSCORE_INSTANCE_H_
@@ -21,12 +18,13 @@
#include "SourceImpl.h"
#include "Telemetry.h"
#include "UnlimitedHandleResource.h"
+#include "UsbCameraListener.h"
namespace cs {
struct SourceData {
SourceData(CS_SourceKind kind_, std::shared_ptr<SourceImpl> source_)
- : kind{kind_}, refCount{0}, source{source_} {}
+ : kind{kind_}, refCount{0}, source{std::move(source_)} {}
CS_SourceKind kind;
std::atomic_int refCount;
@@ -35,7 +33,7 @@
struct SinkData {
explicit SinkData(CS_SinkKind kind_, std::shared_ptr<SinkImpl> sink_)
- : kind{kind_}, refCount{0}, sourceHandle{0}, sink{sink_} {}
+ : kind{kind_}, refCount{0}, sourceHandle{0}, sink{std::move(sink_)} {}
CS_SinkKind kind;
std::atomic_int refCount;
@@ -57,6 +55,7 @@
Notifier notifier;
Telemetry telemetry;
NetworkListener networkListener;
+ UsbCameraListener usbCameraListener;
private:
UnlimitedHandleResource<Handle, SourceData, Handle::kSource> m_sources;
@@ -87,21 +86,22 @@
void DestroySource(CS_Source handle);
void DestroySink(CS_Sink handle);
- wpi::ArrayRef<CS_Source> EnumerateSourceHandles(
+ wpi::span<CS_Source> EnumerateSourceHandles(
wpi::SmallVectorImpl<CS_Source>& vec) {
return m_sources.GetAll(vec);
}
- wpi::ArrayRef<CS_Sink> EnumerateSinkHandles(
- wpi::SmallVectorImpl<CS_Sink>& vec) {
+ wpi::span<CS_Sink> EnumerateSinkHandles(wpi::SmallVectorImpl<CS_Sink>& vec) {
return m_sinks.GetAll(vec);
}
- wpi::ArrayRef<CS_Sink> EnumerateSourceSinks(
- CS_Source source, wpi::SmallVectorImpl<CS_Sink>& vec) {
+ wpi::span<CS_Sink> EnumerateSourceSinks(CS_Source source,
+ wpi::SmallVectorImpl<CS_Sink>& vec) {
vec.clear();
m_sinks.ForEach([&](CS_Sink sinkHandle, const SinkData& data) {
- if (source == data.sourceHandle.load()) vec.push_back(sinkHandle);
+ if (source == data.sourceHandle.load()) {
+ vec.push_back(sinkHandle);
+ }
});
return vec;
}
diff --git a/cscore/src/main/native/cpp/JpegUtil.cpp b/cscore/src/main/native/cpp/JpegUtil.cpp
index 35891e8..2e66338 100644
--- a/cscore/src/main/native/cpp/JpegUtil.cpp
+++ b/cscore/src/main/native/cpp/JpegUtil.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2018 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#include "JpegUtil.h"
@@ -49,29 +46,44 @@
0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa};
-bool IsJpeg(wpi::StringRef data) {
- if (data.size() < 11) return false;
+bool IsJpeg(std::string_view data) {
+ if (data.size() < 11) {
+ return false;
+ }
// Check for valid SOI
- auto bytes = data.bytes_begin();
- if (bytes[0] != 0xff || bytes[1] != 0xd8) return false;
+ auto bytes = reinterpret_cast<const unsigned char*>(data.data());
+ if (bytes[0] != 0xff || bytes[1] != 0xd8) {
+ return false;
+ }
return true;
}
-bool GetJpegSize(wpi::StringRef data, int* width, int* height) {
- if (!IsJpeg(data)) return false;
+bool GetJpegSize(std::string_view data, int* width, int* height) {
+ if (!IsJpeg(data)) {
+ return false;
+ }
data = data.substr(2); // Get to the first block
- auto bytes = data.bytes_begin();
for (;;) {
- if (data.size() < 4) return false; // EOF
- bytes = data.bytes_begin();
- if (bytes[0] != 0xff) return false; // not a tag
- if (bytes[1] == 0xd9) return false; // EOI without finding SOF?
- if (bytes[1] == 0xda) return false; // SOS without finding SOF?
+ if (data.size() < 4) {
+ return false; // EOF
+ }
+ auto bytes = reinterpret_cast<const unsigned char*>(data.data());
+ if (bytes[0] != 0xff) {
+ return false; // not a tag
+ }
+ if (bytes[1] == 0xd9) {
+ return false; // EOI without finding SOF?
+ }
+ if (bytes[1] == 0xda) {
+ return false; // SOS without finding SOF?
+ }
if (bytes[1] == 0xc0) {
// SOF contains the file size
- if (data.size() < 9) return false;
+ if (data.size() < 9) {
+ return false;
+ }
*height = bytes[5] * 256 + bytes[6];
*width = bytes[7] * 256 + bytes[8];
return true;
@@ -82,21 +94,32 @@
}
bool JpegNeedsDHT(const char* data, size_t* size, size_t* locSOF) {
- wpi::StringRef sdata(data, *size);
- if (!IsJpeg(sdata)) return false;
+ std::string_view sdata(data, *size);
+ if (!IsJpeg(sdata)) {
+ return false;
+ }
*locSOF = *size;
// Search until SOS for DHT tag
sdata = sdata.substr(2); // Get to the first block
- auto bytes = sdata.bytes_begin();
for (;;) {
- if (sdata.size() < 4) return false; // EOF
- bytes = sdata.bytes_begin();
- if (bytes[0] != 0xff) return false; // not a tag
- if (bytes[1] == 0xda) break; // SOS
- if (bytes[1] == 0xc4) return false; // DHT
- if (bytes[1] == 0xc0) *locSOF = sdata.data() - data; // SOF
+ if (sdata.size() < 4) {
+ return false; // EOF
+ }
+ auto bytes = reinterpret_cast<const unsigned char*>(sdata.data());
+ if (bytes[0] != 0xff) {
+ return false; // not a tag
+ }
+ if (bytes[1] == 0xda) {
+ break; // SOS
+ }
+ if (bytes[1] == 0xc4) {
+ return false; // DHT
+ }
+ if (bytes[1] == 0xc0) {
+ *locSOF = sdata.data() - data; // SOF
+ }
// Go to the next block
sdata = sdata.substr(bytes[2] * 256 + bytes[3] + 2);
}
@@ -109,9 +132,8 @@
return false;
}
-wpi::StringRef JpegGetDHT() {
- return wpi::StringRef(reinterpret_cast<const char*>(dhtData),
- sizeof(dhtData));
+std::string_view JpegGetDHT() {
+ return {reinterpret_cast<const char*>(dhtData), sizeof(dhtData)};
}
static inline void ReadInto(wpi::raw_istream& is, std::string& buf,
@@ -129,18 +151,26 @@
// read SOI and first marker
buf.resize(4);
is.read(&(*buf.begin()), 4);
- if (is.has_error()) return false;
+ if (is.has_error()) {
+ return false;
+ }
// Check for valid SOI
auto bytes = reinterpret_cast<const unsigned char*>(buf.data());
- if (bytes[0] != 0xff || bytes[1] != 0xd8) return false;
+ if (bytes[0] != 0xff || bytes[1] != 0xd8) {
+ return false;
+ }
size_t pos = 2; // point to first marker
for (;;) {
bytes = reinterpret_cast<const unsigned char*>(buf.data() + pos);
- if (bytes[0] != 0xff) return false; // not a marker
+ if (bytes[0] != 0xff) {
+ return false; // not a marker
+ }
unsigned char marker = bytes[1];
- if (marker == 0xd9) return true; // EOI, we're done
+ if (marker == 0xd9) {
+ return true; // EOI, we're done
+ }
if (marker == 0xda) {
// SOS: need to keep reading until we reach a normal marker.
@@ -150,12 +180,15 @@
bool maybeMarker = false;
for (;;) {
ReadInto(is, buf, 1);
- if (is.has_error()) return false;
+ if (is.has_error()) {
+ return false;
+ }
bytes = reinterpret_cast<const unsigned char*>(buf.data() + pos);
if (maybeMarker) {
if (bytes[0] != 0x00 && bytes[0] != 0xff &&
- (bytes[0] < 0xd0 || bytes[0] > 0xd7))
+ (bytes[0] < 0xd0 || bytes[0] > 0xd7)) {
break;
+ }
maybeMarker = false;
} else if (bytes[0] == 0xff) {
maybeMarker = true;
@@ -168,7 +201,9 @@
// A normal block. Read the length
ReadInto(is, buf, 2); // read length
- if (is.has_error()) return false;
+ if (is.has_error()) {
+ return false;
+ }
// Point to length
pos += 2;
@@ -177,7 +212,9 @@
// Read the block and the next marker
size_t blockLength = bytes[0] * 256 + bytes[1];
ReadInto(is, buf, blockLength);
- if (is.has_error()) return false;
+ if (is.has_error()) {
+ return false;
+ }
bytes = reinterpret_cast<const unsigned char*>(buf.data() + pos);
// Special block processing
diff --git a/cscore/src/main/native/cpp/JpegUtil.h b/cscore/src/main/native/cpp/JpegUtil.h
index 082fdc4..4fe0693 100644
--- a/cscore/src/main/native/cpp/JpegUtil.h
+++ b/cscore/src/main/native/cpp/JpegUtil.h
@@ -1,16 +1,12 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2018 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#ifndef CSCORE_JPEGUTIL_H_
#define CSCORE_JPEGUTIL_H_
#include <string>
-
-#include <wpi/StringRef.h>
+#include <string_view>
namespace wpi {
class raw_istream;
@@ -18,13 +14,13 @@
namespace cs {
-bool IsJpeg(wpi::StringRef data);
+bool IsJpeg(std::string_view data);
-bool GetJpegSize(wpi::StringRef data, int* width, int* height);
+bool GetJpegSize(std::string_view data, int* width, int* height);
bool JpegNeedsDHT(const char* data, size_t* size, size_t* locSOF);
-wpi::StringRef JpegGetDHT();
+std::string_view JpegGetDHT();
bool ReadJpeg(wpi::raw_istream& is, std::string& buf, int* width, int* height);
diff --git a/cscore/src/main/native/cpp/Log.cpp b/cscore/src/main/native/cpp/Log.cpp
new file mode 100644
index 0000000..cf671bb
--- /dev/null
+++ b/cscore/src/main/native/cpp/Log.cpp
@@ -0,0 +1,15 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+#include "Log.h"
+
+void cs::NamedLogV(wpi::Logger& logger, unsigned int level, const char* file,
+ unsigned int line, std::string_view name,
+ fmt::string_view format, fmt::format_args args) {
+ fmt::memory_buffer out;
+ fmt::format_to(fmt::appender{out}, "{}: ", name);
+ fmt::vformat_to(fmt::appender{out}, format, args);
+ out.push_back('\0');
+ logger.DoLog(level, file, line, out.data());
+}
diff --git a/cscore/src/main/native/cpp/Log.h b/cscore/src/main/native/cpp/Log.h
index b9fd9ab..21becdf 100644
--- a/cscore/src/main/native/cpp/Log.h
+++ b/cscore/src/main/native/cpp/Log.h
@@ -1,36 +1,75 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#ifndef CSCORE_LOG_H_
#define CSCORE_LOG_H_
+#include <string_view>
+
#include <wpi/Logger.h>
-#define LOG(level, x) WPI_LOG(m_logger, level, x)
+namespace cs {
+
+void NamedLogV(wpi::Logger& logger, unsigned int level, const char* file,
+ unsigned int line, std::string_view name,
+ fmt::string_view format, fmt::format_args args);
+
+template <typename S, typename... Args>
+inline void NamedLog(wpi::Logger& logger, unsigned int level, const char* file,
+ unsigned int line, std::string_view name, const S& format,
+ Args&&... args) {
+ if (logger.HasLogger() && level >= logger.min_level()) {
+ NamedLogV(logger, level, file, line, name, format,
+ fmt::make_args_checked<Args...>(format, args...));
+ }
+}
+
+} // namespace cs
+
+#define LOG(level, format, ...) WPI_LOG(m_logger, level, format, __VA_ARGS__)
#undef ERROR
-#define ERROR(x) WPI_ERROR(m_logger, x)
-#define WARNING(x) WPI_WARNING(m_logger, x)
-#define INFO(x) WPI_INFO(m_logger, x)
+#define ERROR(format, ...) WPI_ERROR(m_logger, format, __VA_ARGS__)
+#define WARNING(format, ...) WPI_WARNING(m_logger, format, __VA_ARGS__)
+#define INFO(format, ...) WPI_INFO(m_logger, format, __VA_ARGS__)
-#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)
-#define DEBUG4(x) WPI_DEBUG4(m_logger, x)
+#define DEBUG0(format, ...) WPI_DEBUG(m_logger, format, __VA_ARGS__)
+#define DEBUG1(format, ...) WPI_DEBUG1(m_logger, format, __VA_ARGS__)
+#define DEBUG2(format, ...) WPI_DEBUG2(m_logger, format, __VA_ARGS__)
+#define DEBUG3(format, ...) WPI_DEBUG3(m_logger, format, __VA_ARGS__)
+#define DEBUG4(format, ...) WPI_DEBUG4(m_logger, format, __VA_ARGS__)
-#define SERROR(x) ERROR(GetName() << ": " << x)
-#define SWARNING(x) WARNING(GetName() << ": " << x)
-#define SINFO(x) INFO(GetName() << ": " << x)
+#define SLOG(level, format, ...) \
+ NamedLog(m_logger, level, __FILE__, __LINE__, GetName(), FMT_STRING(format), \
+ __VA_ARGS__)
-#define SDEBUG(x) DEBUG0(GetName() << ": " << x)
-#define SDEBUG1(x) DEBUG1(GetName() << ": " << x)
-#define SDEBUG2(x) DEBUG2(GetName() << ": " << x)
-#define SDEBUG3(x) DEBUG3(GetName() << ": " << x)
-#define SDEBUG4(x) DEBUG4(GetName() << ": " << x)
+#define SERROR(format, ...) SLOG(::wpi::WPI_LOG_ERROR, format, __VA_ARGS__)
+#define SWARNING(format, ...) SLOG(::wpi::WPI_LOG_WARNING, format, __VA_ARGS__)
+#define SINFO(format, ...) SLOG(::wpi::WPI_LOG_INFO, format, __VA_ARGS__)
+
+#ifdef NDEBUG
+#define SDEBUG(format, ...) \
+ do { \
+ } while (0)
+#define SDEBUG1(format, ...) \
+ do { \
+ } while (0)
+#define SDEBUG2(format, ...) \
+ do { \
+ } while (0)
+#define SDEBUG3(format, ...) \
+ do { \
+ } while (0)
+#define SDEBUG4(format, ...) \
+ do { \
+ } while (0)
+#else
+#define SDEBUG(format, ...) SLOG(::wpi::WPI_LOG_DEBUG, format, __VA_ARGS__)
+#define SDEBUG1(format, ...) SLOG(::wpi::WPI_LOG_DEBUG1, format, __VA_ARGS__)
+#define SDEBUG2(format, ...) SLOG(::wpi::WPI_LOG_DEBUG2, format, __VA_ARGS__)
+#define SDEBUG3(format, ...) SLOG(::wpi::WPI_LOG_DEBUG3, format, __VA_ARGS__)
+#define SDEBUG4(format, ...) SLOG(::wpi::WPI_LOG_DEBUG4, format, __VA_ARGS__)
+#endif
#endif // CSCORE_LOG_H_
diff --git a/cscore/src/main/native/cpp/MjpegServerImpl.cpp b/cscore/src/main/native/cpp/MjpegServerImpl.cpp
index e30b745..92c23ff 100644
--- a/cscore/src/main/native/cpp/MjpegServerImpl.cpp
+++ b/cscore/src/main/native/cpp/MjpegServerImpl.cpp
@@ -1,17 +1,17 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#include "MjpegServerImpl.h"
#include <chrono>
+#include <fmt/format.h>
#include <wpi/HttpUtil.h>
#include <wpi/SmallString.h>
+#include <wpi/StringExtras.h>
#include <wpi/TCPAcceptor.h>
+#include <wpi/fmt/raw_ostream.h>
#include <wpi/raw_socket_istream.h>
#include <wpi/raw_socket_ostream.h>
@@ -75,13 +75,13 @@
class MjpegServerImpl::ConnThread : public wpi::SafeThread {
public:
- explicit ConnThread(const wpi::Twine& name, wpi::Logger& logger)
- : m_name(name.str()), m_logger(logger) {}
+ explicit ConnThread(std::string_view name, wpi::Logger& logger)
+ : m_name(name), m_logger(logger) {}
- void Main();
+ void Main() override;
bool ProcessCommand(wpi::raw_ostream& os, SourceImpl& source,
- wpi::StringRef parameters, bool respond);
+ std::string_view parameters, bool respond);
void SendJSON(wpi::raw_ostream& os, SourceImpl& source, bool header);
void SendHTMLHeadTitle(wpi::raw_ostream& os) const;
void SendHTML(wpi::raw_ostream& os, SourceImpl& source, bool header);
@@ -102,7 +102,7 @@
std::string m_name;
wpi::Logger& m_logger;
- wpi::StringRef GetName() { return m_name; }
+ std::string_view GetName() { return m_name; }
std::shared_ptr<SourceImpl> GetSource() {
std::scoped_lock lock(m_mutex);
@@ -111,13 +111,17 @@
void StartStream() {
std::scoped_lock lock(m_mutex);
- if (m_source) m_source->EnableSink();
+ if (m_source) {
+ m_source->EnableSink();
+ }
m_streaming = true;
}
void StopStream() {
std::scoped_lock lock(m_mutex);
- if (m_source) m_source->DisableSink();
+ if (m_source) {
+ m_source->DisableSink();
+ }
m_streaming = false;
}
};
@@ -129,10 +133,9 @@
// Using cached pictures would lead to showing old/outdated pictures.
// Many browsers seem to ignore, or at least not always obey, those headers.
static void SendHeader(wpi::raw_ostream& os, int code,
- const wpi::Twine& codeText,
- const wpi::Twine& contentType,
- const wpi::Twine& extra = wpi::Twine{}) {
- os << "HTTP/1.0 " << code << ' ' << codeText << "\r\n";
+ std::string_view codeText, std::string_view contentType,
+ std::string_view extra = {}) {
+ fmt::print(os, "HTTP/1.0 {} {}\r\n", code, codeText);
os << "Connection: close\r\n"
"Server: CameraServer/1.0\r\n"
"Cache-Control: no-store, no-cache, must-revalidate, pre-check=0, "
@@ -141,9 +144,9 @@
"Expires: Mon, 3 Jan 2000 12:34:56 GMT\r\n";
os << "Content-Type: " << contentType << "\r\n";
os << "Access-Control-Allow-Origin: *\r\nAccess-Control-Allow-Methods: *\r\n";
- wpi::SmallString<128> extraBuf;
- wpi::StringRef extraStr = extra.toStringRef(extraBuf);
- if (!extraStr.empty()) os << extraStr << "\r\n";
+ if (!extra.empty()) {
+ os << extra << "\r\n";
+ }
os << "\r\n"; // header ends with a blank line
}
@@ -151,8 +154,8 @@
// @param code HTTP error code (e.g. 404)
// @param message Additional message text
static void SendError(wpi::raw_ostream& os, int code,
- const wpi::Twine& message) {
- wpi::StringRef codeText, extra, baseMessage;
+ std::string_view message) {
+ std::string_view codeText, extra, baseMessage;
switch (code) {
case 401:
codeText = "Unauthorized";
@@ -192,62 +195,61 @@
// Perform a command specified by HTTP GET parameters.
bool MjpegServerImpl::ConnThread::ProcessCommand(wpi::raw_ostream& os,
SourceImpl& source,
- wpi::StringRef parameters,
+ std::string_view parameters,
bool respond) {
wpi::SmallString<256> responseBuf;
wpi::raw_svector_ostream response{responseBuf};
// command format: param1=value1¶m2=value2...
while (!parameters.empty()) {
// split out next param and value
- wpi::StringRef rawParam, rawValue;
- std::tie(rawParam, parameters) = parameters.split('&');
- if (rawParam.empty()) continue; // ignore "&&"
- std::tie(rawParam, rawValue) = rawParam.split('=');
- if (rawParam.empty() || rawValue.empty()) continue; // ignore "param="
- SDEBUG4("HTTP parameter \"" << rawParam << "\" value \"" << rawValue
- << "\"");
+ std::string_view rawParam, rawValue;
+ std::tie(rawParam, parameters) = wpi::split(parameters, '&');
+ if (rawParam.empty()) {
+ continue; // ignore "&&"
+ }
+ std::tie(rawParam, rawValue) = wpi::split(rawParam, '=');
+ if (rawParam.empty() || rawValue.empty()) {
+ continue; // ignore "param="
+ }
+ SDEBUG4("HTTP parameter \"{}\" value \"{}\"", rawParam, rawValue);
// unescape param
bool error = false;
wpi::SmallString<64> paramBuf;
- wpi::StringRef param = wpi::UnescapeURI(rawParam, paramBuf, &error);
+ std::string_view param = wpi::UnescapeURI(rawParam, paramBuf, &error);
if (error) {
- wpi::SmallString<128> error;
- wpi::raw_svector_ostream oss{error};
- oss << "could not unescape parameter \"" << rawParam << "\"";
- SendError(os, 500, error.str());
- SDEBUG(error.str());
+ auto estr = fmt::format("could not unescape parameter \"{}\"", rawParam);
+ SendError(os, 500, estr);
+ SDEBUG("{}", estr);
return false;
}
// unescape value
wpi::SmallString<64> valueBuf;
- wpi::StringRef value = wpi::UnescapeURI(rawValue, valueBuf, &error);
+ std::string_view value = wpi::UnescapeURI(rawValue, valueBuf, &error);
if (error) {
- wpi::SmallString<128> error;
- wpi::raw_svector_ostream oss{error};
- oss << "could not unescape value \"" << rawValue << "\"";
- SendError(os, 500, error.str());
- SDEBUG(error.str());
+ auto estr = fmt::format("could not unescape value \"{}\"", rawValue);
+ SendError(os, 500, estr);
+ SDEBUG("{}", estr);
return false;
}
// Handle resolution, compression, and FPS. These are handled locally
// rather than passed to the source.
if (param == "resolution") {
- wpi::StringRef widthStr, heightStr;
- std::tie(widthStr, heightStr) = value.split('x');
- int width, height;
- if (widthStr.getAsInteger(10, width)) {
+ auto [widthStr, heightStr] = wpi::split(value, 'x');
+ int width = wpi::parse_integer<int>(widthStr, 10).value_or(-1);
+ int height = wpi::parse_integer<int>(heightStr, 10).value_or(-1);
+ if (width < 0) {
response << param << ": \"width is not an integer\"\r\n";
- SWARNING("HTTP parameter \"" << param << "\" width \"" << widthStr
- << "\" is not an integer");
+ SWARNING("HTTP parameter \"{}\" width \"{}\" is not an integer", param,
+ widthStr);
continue;
}
- if (heightStr.getAsInteger(10, height)) {
+ if (height < 0) {
response << param << ": \"height is not an integer\"\r\n";
- SWARNING("HTTP parameter \"" << param << "\" height \"" << heightStr
- << "\" is not an integer");
+ SWARNING("HTTP parameter \"{}\" height \"{}\" is not an integer", param,
+ heightStr);
continue;
}
m_width = width;
@@ -257,41 +259,39 @@
}
if (param == "fps") {
- int fps;
- if (value.getAsInteger(10, fps)) {
- response << param << ": \"invalid integer\"\r\n";
- SWARNING("HTTP parameter \"" << param << "\" value \"" << value
- << "\" is not an integer");
- continue;
- } else {
- m_fps = fps;
+ if (auto v = wpi::parse_integer<int>(value, 10)) {
+ m_fps = v.value();
response << param << ": \"ok\"\r\n";
+ } else {
+ response << param << ": \"invalid integer\"\r\n";
+ SWARNING("HTTP parameter \"{}\" value \"{}\" is not an integer", param,
+ value);
}
continue;
}
if (param == "compression") {
- int compression;
- if (value.getAsInteger(10, compression)) {
- response << param << ": \"invalid integer\"\r\n";
- SWARNING("HTTP parameter \"" << param << "\" value \"" << value
- << "\" is not an integer");
- continue;
- } else {
- m_compression = compression;
+ if (auto v = wpi::parse_integer<int>(value, 10)) {
+ m_compression = v.value();
response << param << ": \"ok\"\r\n";
+ } else {
+ response << param << ": \"invalid integer\"\r\n";
+ SWARNING("HTTP parameter \"{}\" value \"{}\" is not an integer", param,
+ value);
}
continue;
}
// ignore name parameter
- if (param == "name") continue;
+ if (param == "name") {
+ continue;
+ }
// try to assign parameter
auto prop = source.GetPropertyIndex(param);
if (!prop) {
response << param << ": \"ignored\"\r\n";
- SWARNING("ignoring HTTP parameter \"" << param << "\"");
+ SWARNING("ignoring HTTP parameter \"{}\"", param);
continue;
}
@@ -301,21 +301,20 @@
case CS_PROP_BOOLEAN:
case CS_PROP_INTEGER:
case CS_PROP_ENUM: {
- int val = 0;
- if (value.getAsInteger(10, val)) {
- response << param << ": \"invalid integer\"\r\n";
- SWARNING("HTTP parameter \"" << param << "\" value \"" << value
- << "\" is not an integer");
+ if (auto v = wpi::parse_integer<int>(value, 10)) {
+ fmt::print(response, "{}: {}\r\n", param, v.value());
+ SDEBUG4("HTTP parameter \"{}\" value {}", param, value);
+ source.SetProperty(prop, v.value(), &status);
} else {
- response << param << ": " << val << "\r\n";
- SDEBUG4("HTTP parameter \"" << param << "\" value " << value);
- source.SetProperty(prop, val, &status);
+ response << param << ": \"invalid integer\"\r\n";
+ SWARNING("HTTP parameter \"{}\" value \"{}\" is not an integer",
+ param, value);
}
break;
}
case CS_PROP_STRING: {
response << param << ": \"ok\"\r\n";
- SDEBUG4("HTTP parameter \"" << param << "\" value \"" << value << "\"");
+ SDEBUG4("HTTP parameter \"{}\" value \"{}\"", param, value);
source.SetStringProperty(prop, value, &status);
break;
}
@@ -342,7 +341,9 @@
// Send the root html file with controls for all the settable properties.
void MjpegServerImpl::ConnThread::SendHTML(wpi::raw_ostream& os,
SourceImpl& source, bool header) {
- if (header) SendHeader(os, 200, "OK", "text/html");
+ if (header) {
+ SendHeader(os, 200, "OK", "text/html");
+ }
SendHTMLHeadTitle(os);
os << startRootPage;
@@ -351,31 +352,35 @@
for (auto prop : source.EnumerateProperties(properties_vec, &status)) {
wpi::SmallString<128> name_buf;
auto name = source.GetPropertyName(prop, name_buf, &status);
- if (name.startswith("raw_")) continue;
+ if (wpi::starts_with(name, "raw_")) {
+ continue;
+ }
auto kind = source.GetPropertyKind(prop);
- os << "<p />"
- << "<label for=\"" << name << "\">" << name << "</label>\n";
+ fmt::print(os, "<p /><label for=\"{0}\">{0}</label>\n", name);
switch (kind) {
case CS_PROP_BOOLEAN:
- os << "<input id=\"" << name
- << "\" type=\"checkbox\" onclick=\"update('" << name
- << "', this.checked ? 1 : 0)\" ";
- if (source.GetProperty(prop, &status) != 0)
+ fmt::print(os,
+ "<input id=\"{0}\" type=\"checkbox\" "
+ "onclick=\"update('{0}', this.checked ? 1 : 0)\" ",
+ name);
+ if (source.GetProperty(prop, &status) != 0) {
os << "checked />\n";
- else
+ } else {
os << " />\n";
+ }
break;
case CS_PROP_INTEGER: {
auto valI = source.GetProperty(prop, &status);
auto min = source.GetPropertyMin(prop, &status);
auto max = source.GetPropertyMax(prop, &status);
auto step = source.GetPropertyStep(prop, &status);
- os << "<input type=\"range\" min=\"" << min << "\" max=\"" << max
- << "\" value=\"" << valI << "\" id=\"" << name << "\" step=\""
- << step << "\" oninput=\"updateInt('#" << name << "op', '" << name
- << "', value)\" />\n";
- os << "<output for=\"" << name << "\" id=\"" << name << "op\">" << valI
- << "</output>\n";
+ fmt::print(os,
+ "<input type=\"range\" min=\"{1}\" max=\"{2}\" "
+ "value=\"{3}\" id=\"{0}\" step=\"{4}\" "
+ "oninput=\"updateInt('#{0}op', '{0}', value)\" />\n",
+ name, min, max, valI, step);
+ fmt::print(os, "<output for=\"{0}\" id=\"{0}op\">{1}</output>\n", name,
+ valI);
break;
}
case CS_PROP_ENUM: {
@@ -384,29 +389,36 @@
int j = 0;
for (auto choice = choices.begin(), end = choices.end(); choice != end;
++j, ++choice) {
- if (choice->empty()) continue; // skip empty choices
+ if (choice->empty()) {
+ continue; // skip empty choices
+ }
// replace any non-printable characters in name with spaces
wpi::SmallString<128> ch_name;
- for (char ch : *choice)
- ch_name.push_back(std::isprint(ch) ? ch : ' ');
- os << "<input id=\"" << name << j << "\" type=\"radio\" name=\""
- << name << "\" value=\"" << ch_name << "\" onclick=\"update('"
- << name << "', " << j << ")\"";
+ for (char ch : *choice) {
+ ch_name.push_back(wpi::isPrint(ch) ? ch : ' ');
+ }
+ fmt::print(os,
+ "<input id=\"{0}{1}\" type=\"radio\" name=\"{0}\" "
+ "value=\"{2}\" onclick=\"update('{0}', {1})\"",
+ name, j, ch_name);
if (j == valE) {
os << " checked";
}
- os << " /><label for=\"" << name << j << "\">" << ch_name
- << "</label>\n";
+ fmt::print(os, " /><label for=\"{}{}\">{}</label>\n", name, j,
+ ch_name);
}
break;
}
case CS_PROP_STRING: {
wpi::SmallString<128> strval_buf;
- os << "<input type=\"text\" id=\"" << name << "box\" name=\"" << name
- << "\" value=\""
- << source.GetStringProperty(prop, strval_buf, &status) << "\" />\n";
- os << "<input type=\"button\" value =\"Submit\" onclick=\"update('"
- << name << "', " << name << "box.value)\" />\n";
+ fmt::print(os,
+ "<input type=\"text\" id=\"{0}box\" name=\"{0}\" "
+ "value=\"{1}\" />\n",
+ name, source.GetStringProperty(prop, strval_buf, &status));
+ fmt::print(os,
+ "<input type=\"button\" value =\"Submit\" "
+ "onclick=\"update('{0}', {0}box.value)\" />\n",
+ name);
break;
}
default:
@@ -419,8 +431,9 @@
&status);
if (status == CS_OK) {
os << "<p>USB device path: " << info.path << '\n';
- for (auto&& path : info.otherPaths)
+ for (auto&& path : info.otherPaths) {
os << "<p>Alternate device path: " << path << '\n';
+ }
}
os << "<p>Supported Video Modes:</p>\n";
@@ -451,10 +464,8 @@
os << "unknown";
break;
}
- os << "</td><td>" << mode.width;
- os << "</td><td>" << mode.height;
- os << "</td><td>" << mode.fps;
- os << "</td></tr>";
+ fmt::print(os, "</td><td>{}</td><td>{}</td><td>{}</td></tr>", mode.width,
+ mode.height, mode.fps);
}
os << "</table>\n";
os << endRootPage << "\r\n";
@@ -464,35 +475,39 @@
// Send a JSON file which is contains information about the source parameters.
void MjpegServerImpl::ConnThread::SendJSON(wpi::raw_ostream& os,
SourceImpl& source, bool header) {
- if (header) SendHeader(os, 200, "OK", "application/json");
+ if (header) {
+ SendHeader(os, 200, "OK", "application/json");
+ }
os << "{\n\"controls\": [\n";
wpi::SmallVector<int, 32> properties_vec;
bool first = true;
CS_Status status = 0;
for (auto prop : source.EnumerateProperties(properties_vec, &status)) {
- if (first)
+ if (first) {
first = false;
- else
+ } else {
os << ",\n";
+ }
os << '{';
wpi::SmallString<128> name_buf;
auto name = source.GetPropertyName(prop, name_buf, &status);
auto kind = source.GetPropertyKind(prop);
- os << "\n\"name\": \"" << name << '"';
- os << ",\n\"id\": \"" << prop << '"';
- os << ",\n\"type\": \"" << kind << '"';
- os << ",\n\"min\": \"" << source.GetPropertyMin(prop, &status) << '"';
- os << ",\n\"max\": \"" << source.GetPropertyMax(prop, &status) << '"';
- os << ",\n\"step\": \"" << source.GetPropertyStep(prop, &status) << '"';
- os << ",\n\"default\": \"" << source.GetPropertyDefault(prop, &status)
- << '"';
+ fmt::print(os, "\n\"name\": \"{}\"", name);
+ fmt::print(os, ",\n\"id\": \"{}\"", prop);
+ fmt::print(os, ",\n\"type\": \"{}\"", kind);
+ fmt::print(os, ",\n\"min\": \"{}\"", source.GetPropertyMin(prop, &status));
+ fmt::print(os, ",\n\"max\": \"{}\"", source.GetPropertyMax(prop, &status));
+ fmt::print(os, ",\n\"step\": \"{}\"",
+ source.GetPropertyStep(prop, &status));
+ fmt::print(os, ",\n\"default\": \"{}\"",
+ source.GetPropertyDefault(prop, &status));
os << ",\n\"value\": \"";
switch (kind) {
case CS_PROP_BOOLEAN:
case CS_PROP_INTEGER:
case CS_PROP_ENUM:
- os << source.GetProperty(prop, &status);
+ fmt::print(os, "{}", source.GetProperty(prop, &status));
break;
case CS_PROP_STRING: {
wpi::SmallString<128> strval_buf;
@@ -514,11 +529,15 @@
int j = 0;
for (auto choice = choices.begin(), end = choices.end(); choice != end;
++j, ++choice) {
- if (j != 0) os << ", ";
+ if (j != 0) {
+ os << ", ";
+ }
// replace any non-printable characters in name with spaces
wpi::SmallString<128> ch_name;
- for (char ch : *choice) ch_name.push_back(std::isprint(ch) ? ch : ' ');
- os << '"' << j << "\": \"" << ch_name << '"';
+ for (char ch : *choice) {
+ ch_name.push_back(std::isprint(ch) ? ch : ' ');
+ }
+ fmt::print(os, "\"{}\": \"{}\"", j, ch_name);
}
os << "}\n";
}
@@ -527,10 +546,11 @@
os << "\n],\n\"modes\": [\n";
first = true;
for (auto mode : source.EnumerateVideoModes(&status)) {
- if (first)
+ if (first) {
first = false;
- else
+ } else {
os << ",\n";
+ }
os << '{';
os << "\n\"pixelFormat\": \"";
switch (mode.pixelFormat) {
@@ -553,29 +573,26 @@
os << "unknown";
break;
}
- os << "\",\n\"width\": \"" << mode.width << '"';
- os << ",\n\"height\": \"" << mode.height << '"';
- os << ",\n\"fps\": \"" << mode.fps << '"';
+ fmt::print(os, "\",\n\"width\": \"{}\"", mode.width);
+ fmt::print(os, ",\n\"height\": \"{}\"", mode.height);
+ fmt::print(os, ",\n\"fps\": \"{}\"", mode.fps);
os << '}';
}
os << "\n]\n}\n";
os.flush();
}
-MjpegServerImpl::MjpegServerImpl(const wpi::Twine& name, wpi::Logger& logger,
+MjpegServerImpl::MjpegServerImpl(std::string_view name, wpi::Logger& logger,
Notifier& notifier, Telemetry& telemetry,
- const wpi::Twine& listenAddress, int port,
+ std::string_view listenAddress, int port,
std::unique_ptr<wpi::NetworkAcceptor> acceptor)
: SinkImpl{name, logger, notifier, telemetry},
- m_listenAddress(listenAddress.str()),
+ m_listenAddress(listenAddress),
m_port(port),
m_acceptor{std::move(acceptor)} {
m_active = true;
- wpi::SmallString<128> descBuf;
- wpi::raw_svector_ostream desc{descBuf};
- desc << "HTTP Server on port " << port;
- SetDescription(desc.str());
+ SetDescription(fmt::format("HTTP Server on port {}", port));
// Create properties
m_widthProp = CreateProperty("width", [] {
@@ -599,7 +616,9 @@
m_serverThread = std::thread(&MjpegServerImpl::ServerThreadMain, this);
}
-MjpegServerImpl::~MjpegServerImpl() { Stop(); }
+MjpegServerImpl::~MjpegServerImpl() {
+ Stop();
+}
void MjpegServerImpl::Stop() {
m_active = false;
@@ -608,24 +627,30 @@
m_acceptor->shutdown();
// join server thread
- if (m_serverThread.joinable()) m_serverThread.join();
+ if (m_serverThread.joinable()) {
+ m_serverThread.join();
+ }
// close streams
for (auto& connThread : m_connThreads) {
if (auto thr = connThread.GetThread()) {
- if (thr->m_stream) thr->m_stream->close();
+ if (thr->m_stream) {
+ thr->m_stream->close();
+ }
}
connThread.Stop();
}
// wake up connection threads by forcing an empty frame to be sent
- if (auto source = GetSource()) source->Wakeup();
+ if (auto source = GetSource()) {
+ source->Wakeup();
+ }
}
// Send HTTP response and a stream of JPG-frames
void MjpegServerImpl::ConnThread::SendStream(wpi::raw_socket_ostream& os) {
if (m_noStreaming) {
- SERROR("Too many simultaneous client streams");
+ SERROR("{}", "Too many simultaneous client streams");
SendError(os, 503, "Too many simultaneous streams");
return;
}
@@ -638,14 +663,18 @@
SendHeader(oss, 200, "OK", "multipart/x-mixed-replace;boundary=" BOUNDARY);
os << oss.str();
- SDEBUG("Headers send, sending stream now");
+ SDEBUG("{}", "Headers send, sending stream now");
Frame::Time lastFrameTime = 0;
Frame::Time timePerFrame = 0;
- if (m_fps != 0) timePerFrame = 1000000.0 / m_fps;
+ if (m_fps != 0) {
+ timePerFrame = 1000000.0 / m_fps;
+ }
Frame::Time averageFrameTime = 0;
Frame::Time averagePeriod = 1000000; // 1 second window
- if (averagePeriod < timePerFrame) averagePeriod = timePerFrame * 10;
+ if (averagePeriod < timePerFrame) {
+ averagePeriod = timePerFrame * 10;
+ }
StartStream();
while (m_active && !os.has_error()) {
@@ -656,9 +685,11 @@
std::this_thread::sleep_for(std::chrono::milliseconds(200));
continue;
}
- SDEBUG4("waiting for frame");
+ SDEBUG4("{}", "waiting for frame");
Frame frame = source->GetNextFrame(0.225); // blocks
- if (!m_active) break;
+ if (!m_active) {
+ break;
+ }
if (!frame) {
// Bad frame; sleep for 20 ms so we don't consume all processor time.
os << "\r\n"; // Keep connection alive
@@ -717,7 +748,7 @@
continue;
}
- SDEBUG4("sending frame size=" << size << " addDHT=" << addDHT);
+ SDEBUG4("sending frame size={} addDHT={}", size, addDHT);
// print the individual mimetype and the length
// sending the content-length fixes random stream disruption observed
@@ -726,18 +757,18 @@
double timestamp = lastFrameTime / 1000000.0;
header.clear();
oss << "\r\n--" BOUNDARY "\r\n"
- << "Content-Type: image/jpeg\r\n"
- << "Content-Length: " << size << "\r\n"
- << "X-Timestamp: " << timestamp << "\r\n"
- << "\r\n";
+ << "Content-Type: image/jpeg\r\n";
+ fmt::print(oss, "Content-Length: {}\r\n", size);
+ fmt::print(oss, "X-Timestamp: {}\r\n", timestamp);
+ oss << "\r\n";
os << oss.str();
if (addDHT) {
// Insert DHT data immediately before SOF
- os << wpi::StringRef(data, locSOF);
+ os << std::string_view(data, locSOF);
os << JpegGetDHT();
- os << wpi::StringRef(data + locSOF, image->size() - locSOF);
+ os << std::string_view(data + locSOF, image->size() - locSOF);
} else {
- os << wpi::StringRef(data, size);
+ os << std::string_view(data, size);
}
// os.flush();
}
@@ -750,48 +781,50 @@
// Read the request string from the stream
wpi::SmallString<128> reqBuf;
- wpi::StringRef req = is.getline(reqBuf, 4096);
+ std::string_view req = is.getline(reqBuf, 4096);
if (is.has_error()) {
- SDEBUG("error getting request string");
+ SDEBUG("{}", "error getting request string");
return;
}
enum { kCommand, kStream, kGetSettings, kGetSourceConfig, kRootPage } kind;
- wpi::StringRef parameters;
+ std::string_view parameters;
size_t pos;
- SDEBUG("HTTP request: '" << req << "'\n");
+ SDEBUG("HTTP request: '{}'\n", req);
// Determine request kind. Most of these are for mjpgstreamer
// compatibility, others are for Axis camera compatibility.
- if ((pos = req.find("POST /stream")) != wpi::StringRef::npos) {
+ if ((pos = req.find("POST /stream")) != std::string_view::npos) {
kind = kStream;
parameters = req.substr(req.find('?', pos + 12)).substr(1);
- } else if ((pos = req.find("GET /?action=stream")) != wpi::StringRef::npos) {
+ } else if ((pos = req.find("GET /?action=stream")) !=
+ std::string_view::npos) {
kind = kStream;
parameters = req.substr(req.find('&', pos + 19)).substr(1);
- } else if ((pos = req.find("GET /stream.mjpg")) != wpi::StringRef::npos) {
+ } else if ((pos = req.find("GET /stream.mjpg")) != std::string_view::npos) {
kind = kStream;
parameters = req.substr(req.find('?', pos + 16)).substr(1);
- } else if (req.find("GET /settings") != wpi::StringRef::npos &&
- req.find(".json") != wpi::StringRef::npos) {
+ } else if (req.find("GET /settings") != std::string_view::npos &&
+ req.find(".json") != std::string_view::npos) {
kind = kGetSettings;
- } else if (req.find("GET /config") != wpi::StringRef::npos &&
- req.find(".json") != wpi::StringRef::npos) {
+ } else if (req.find("GET /config") != std::string_view::npos &&
+ req.find(".json") != std::string_view::npos) {
kind = kGetSourceConfig;
- } else if (req.find("GET /input") != wpi::StringRef::npos &&
- req.find(".json") != wpi::StringRef::npos) {
+ } else if (req.find("GET /input") != std::string_view::npos &&
+ req.find(".json") != std::string_view::npos) {
kind = kGetSettings;
- } else if (req.find("GET /output") != wpi::StringRef::npos &&
- req.find(".json") != wpi::StringRef::npos) {
+ } else if (req.find("GET /output") != std::string_view::npos &&
+ req.find(".json") != std::string_view::npos) {
kind = kGetSettings;
- } else if ((pos = req.find("GET /?action=command")) != wpi::StringRef::npos) {
+ } else if ((pos = req.find("GET /?action=command")) !=
+ std::string_view::npos) {
kind = kCommand;
parameters = req.substr(req.find('&', pos + 20)).substr(1);
- } else if (req.find("GET / ") != wpi::StringRef::npos || req == "GET /\n") {
+ } else if (req.find("GET / ") != std::string_view::npos || req == "GET /\n") {
kind = kRootPage;
} else {
- SDEBUG("HTTP request resource not found");
+ SDEBUG("{}", "HTTP request resource not found");
SendError(os, 404, "Resource not found");
return;
}
@@ -801,22 +834,28 @@
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_"
"-=&1234567890%./");
parameters = parameters.substr(0, pos);
- SDEBUG("command parameters: \"" << parameters << "\"");
+ SDEBUG("command parameters: \"{}\"", parameters);
// Read the rest of the HTTP request.
// The end of the request is marked by a single, empty line
wpi::SmallString<128> lineBuf;
for (;;) {
- if (is.getline(lineBuf, 4096).startswith("\n")) break;
- if (is.has_error()) return;
+ if (wpi::starts_with(is.getline(lineBuf, 4096), "\n")) {
+ break;
+ }
+ if (is.has_error()) {
+ return;
+ }
}
// Send response
switch (kind) {
case kStream:
if (auto source = GetSource()) {
- SDEBUG("request for stream " << source->GetName());
- if (!ProcessCommand(os, *source, parameters, false)) return;
+ SDEBUG("request for stream {}", source->GetName());
+ if (!ProcessCommand(os, *source, parameters, false)) {
+ return;
+ }
}
SendStream(os);
break;
@@ -827,18 +866,19 @@
SendHeader(os, 200, "OK", "text/plain");
os << "Ignored due to no connected source."
<< "\r\n";
- SDEBUG("Ignored due to no connected source.");
+ SDEBUG("{}", "Ignored due to no connected source.");
}
break;
case kGetSettings:
- SDEBUG("request for JSON file");
- if (auto source = GetSource())
+ SDEBUG("{}", "request for JSON file");
+ if (auto source = GetSource()) {
SendJSON(os, *source, true);
- else
+ } else {
SendError(os, 404, "Resource not found");
+ }
break;
case kGetSourceConfig:
- SDEBUG("request for JSON file");
+ SDEBUG("{}", "request for JSON file");
if (auto source = GetSource()) {
SendHeader(os, 200, "OK", "application/json");
CS_Status status = CS_OK;
@@ -849,7 +889,7 @@
}
break;
case kRootPage:
- SDEBUG("request for root page");
+ SDEBUG("{}", "request for root page");
SendHeader(os, 200, "OK", "text/html");
if (auto source = GetSource()) {
SendHTML(os, *source, false);
@@ -860,7 +900,7 @@
break;
}
- SDEBUG("leaving HTTP client thread");
+ SDEBUG("{}", "leaving HTTP client thread");
}
// worker thread for clients that connected to this server
@@ -869,7 +909,9 @@
while (m_active) {
while (!m_stream) {
m_cond.wait(lock);
- if (!m_active) return;
+ if (!m_active) {
+ return;
+ }
}
lock.unlock();
ProcessRequest();
@@ -885,16 +927,18 @@
return;
}
- SDEBUG("waiting for clients to connect");
+ SDEBUG("{}", "waiting for clients to connect");
while (m_active) {
auto stream = m_acceptor->accept();
if (!stream) {
m_active = false;
return;
}
- if (!m_active) return;
+ if (!m_active) {
+ return;
+ }
- SDEBUG("client connection from " << stream->getPeerIP());
+ SDEBUG("client connection from {}", stream->getPeerIP());
auto source = GetSource();
@@ -933,7 +977,7 @@
thr->m_cond.notify_one();
}
- SDEBUG("leaving server thread");
+ SDEBUG("{}", "leaving server thread");
}
void MjpegServerImpl::SetSourceImpl(std::shared_ptr<SourceImpl> source) {
@@ -942,9 +986,13 @@
if (auto thr = connThread.GetThread()) {
if (thr->m_source != source) {
bool streaming = thr->m_streaming;
- if (thr->m_source && streaming) thr->m_source->DisableSink();
+ if (thr->m_source && streaming) {
+ thr->m_source->DisableSink();
+ }
thr->m_source = source;
- if (source && streaming) thr->m_source->EnableSink();
+ if (source && streaming) {
+ thr->m_source->EnableSink();
+ }
}
}
}
@@ -952,19 +1000,15 @@
namespace cs {
-CS_Sink CreateMjpegServer(const wpi::Twine& name,
- const wpi::Twine& listenAddress, int port,
- CS_Status* status) {
+CS_Sink CreateMjpegServer(std::string_view name, std::string_view listenAddress,
+ int port, CS_Status* status) {
auto& inst = Instance::GetInstance();
- wpi::SmallString<128> listenAddressBuf;
return inst.CreateSink(
CS_SINK_MJPEG,
std::make_shared<MjpegServerImpl>(
name, inst.logger, inst.notifier, inst.telemetry, listenAddress, port,
- std::unique_ptr<wpi::NetworkAcceptor>(new wpi::TCPAcceptor(
- port,
- listenAddress.toNullTerminatedStringRef(listenAddressBuf).data(),
- inst.logger))));
+ std::unique_ptr<wpi::NetworkAcceptor>(
+ new wpi::TCPAcceptor(port, listenAddress, inst.logger))));
}
std::string GetMjpegServerListenAddress(CS_Sink sink, CS_Status* status) {
diff --git a/cscore/src/main/native/cpp/MjpegServerImpl.h b/cscore/src/main/native/cpp/MjpegServerImpl.h
index db60b86..e323e69 100644
--- a/cscore/src/main/native/cpp/MjpegServerImpl.h
+++ b/cscore/src/main/native/cpp/MjpegServerImpl.h
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2018 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#ifndef CSCORE_MJPEGSERVERIMPL_H_
#define CSCORE_MJPEGSERVERIMPL_H_
@@ -11,6 +8,7 @@
#include <atomic>
#include <memory>
#include <string>
+#include <string_view>
#include <thread>
#include <vector>
@@ -18,7 +16,6 @@
#include <wpi/NetworkStream.h>
#include <wpi/SafeThread.h>
#include <wpi/SmallVector.h>
-#include <wpi/Twine.h>
#include <wpi/raw_istream.h>
#include <wpi/raw_ostream.h>
#include <wpi/raw_socket_ostream.h>
@@ -31,9 +28,9 @@
class MjpegServerImpl : public SinkImpl {
public:
- MjpegServerImpl(const wpi::Twine& name, wpi::Logger& logger,
+ MjpegServerImpl(std::string_view name, wpi::Logger& logger,
Notifier& notifier, Telemetry& telemetry,
- const wpi::Twine& listenAddress, int port,
+ std::string_view listenAddress, int port,
std::unique_ptr<wpi::NetworkAcceptor> acceptor);
~MjpegServerImpl() override;
diff --git a/cscore/src/main/native/cpp/NetworkListener.h b/cscore/src/main/native/cpp/NetworkListener.h
index 6d49adc..d48de18 100644
--- a/cscore/src/main/native/cpp/NetworkListener.h
+++ b/cscore/src/main/native/cpp/NetworkListener.h
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2015-2018 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#ifndef CSCORE_NETWORKLISTENER_H_
#define CSCORE_NETWORKLISTENER_H_
diff --git a/cscore/src/main/native/cpp/Notifier.cpp b/cscore/src/main/native/cpp/Notifier.cpp
index e4645c9..3711896 100644
--- a/cscore/src/main/native/cpp/Notifier.cpp
+++ b/cscore/src/main/native/cpp/Notifier.cpp
@@ -1,13 +1,11 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#include "Notifier.h"
#include <queue>
+#include <utility>
#include <vector>
#include "Handle.h"
@@ -17,144 +15,26 @@
using namespace cs;
-bool Notifier::s_destroyed = false;
+Notifier::Notifier() {}
-namespace {
-// Vector which provides an integrated freelist for removal and reuse of
-// individual elements.
-template <typename T>
-class UidVector {
- public:
- using size_type = typename std::vector<T>::size_type;
+Notifier::~Notifier() {}
- size_type size() const { return m_vector.size(); }
- T& operator[](size_type i) { return m_vector[i]; }
- const T& operator[](size_type i) const { return m_vector[i]; }
-
- // Add a new T to the vector. If there are elements on the freelist,
- // reuses the last one; otherwise adds to the end of the vector.
- // Returns the resulting element index (+1).
- template <class... Args>
- unsigned int emplace_back(Args&&... args) {
- unsigned int uid;
- if (m_free.empty()) {
- uid = m_vector.size();
- m_vector.emplace_back(std::forward<Args>(args)...);
- } else {
- uid = m_free.back();
- m_free.pop_back();
- m_vector[uid] = T(std::forward<Args>(args)...);
- }
- return uid + 1;
- }
-
- // Removes the identified element by replacing it with a default-constructed
- // one. The element is added to the freelist for later reuse.
- void erase(unsigned int uid) {
- --uid;
- if (uid >= m_vector.size() || !m_vector[uid]) return;
- m_free.push_back(uid);
- m_vector[uid] = T();
- }
-
- private:
- std::vector<T> m_vector;
- std::vector<unsigned int> m_free;
-};
-
-} // namespace
-
-class Notifier::Thread : public wpi::SafeThread {
- public:
- Thread(std::function<void()> on_start, std::function<void()> on_exit)
- : m_on_start(on_start), m_on_exit(on_exit) {}
-
- void Main();
-
- struct Listener {
- Listener() = default;
- Listener(std::function<void(const RawEvent& event)> callback_,
- int eventMask_)
- : callback(callback_), eventMask(eventMask_) {}
-
- explicit operator bool() const { return static_cast<bool>(callback); }
-
- std::string prefix;
- std::function<void(const RawEvent& event)> callback;
- int eventMask;
- };
- UidVector<Listener> m_listeners;
-
- std::queue<RawEvent> m_notifications;
-
- std::function<void()> m_on_start;
- std::function<void()> m_on_exit;
-};
-
-Notifier::Notifier() { s_destroyed = false; }
-
-Notifier::~Notifier() { s_destroyed = true; }
-
-void Notifier::Start() { m_owner.Start(m_on_start, m_on_exit); }
-
-void Notifier::Stop() { m_owner.Stop(); }
-
-void Notifier::Thread::Main() {
- if (m_on_start) m_on_start();
-
- std::unique_lock lock(m_mutex);
- while (m_active) {
- while (m_notifications.empty()) {
- m_cond.wait(lock);
- if (!m_active) goto done;
- }
-
- while (!m_notifications.empty()) {
- if (!m_active) goto done;
- auto item = std::move(m_notifications.front());
- m_notifications.pop();
-
- // Use index because iterator might get invalidated.
- for (size_t i = 0; i < m_listeners.size(); ++i) {
- if (!m_listeners[i]) continue; // removed
-
- // Event type must be within requested set for this listener.
- if ((item.kind & m_listeners[i].eventMask) == 0) continue;
-
- // make a copy of the callback so we can safely release the mutex
- auto callback = m_listeners[i].callback;
-
- // Don't hold mutex during callback execution!
- lock.unlock();
- callback(item);
- lock.lock();
- }
- }
- }
-
-done:
- if (m_on_exit) m_on_exit();
+void Notifier::Start() {
+ DoStart();
}
-int Notifier::AddListener(std::function<void(const RawEvent& event)> callback,
- int eventMask) {
- Start();
- auto thr = m_owner.GetThread();
- return thr->m_listeners.emplace_back(callback, eventMask);
+unsigned int Notifier::Add(std::function<void(const RawEvent& event)> callback,
+ int eventMask) {
+ return DoAdd(callback, eventMask);
}
-void Notifier::RemoveListener(int uid) {
- auto thr = m_owner.GetThread();
- if (!thr) return;
- thr->m_listeners.erase(uid);
+unsigned int Notifier::AddPolled(unsigned int pollerUid, int eventMask) {
+ return DoAdd(pollerUid, eventMask);
}
-void Notifier::NotifySource(const wpi::Twine& name, CS_Source source,
+void Notifier::NotifySource(std::string_view name, CS_Source source,
CS_EventKind kind) {
- auto thr = m_owner.GetThread();
- if (!thr) return;
- thr->m_notifications.emplace(name, source, static_cast<RawEvent::Kind>(kind));
- thr->m_cond.notify_one();
+ Send(UINT_MAX, name, source, static_cast<RawEvent::Kind>(kind));
}
void Notifier::NotifySource(const SourceImpl& source, CS_EventKind kind) {
@@ -164,38 +44,24 @@
void Notifier::NotifySourceVideoMode(const SourceImpl& source,
const VideoMode& mode) {
- auto thr = m_owner.GetThread();
- if (!thr) return;
-
auto handleData = Instance::GetInstance().FindSource(source);
-
- thr->m_notifications.emplace(source.GetName(), handleData.first, mode);
- thr->m_cond.notify_one();
+ Send(UINT_MAX, source.GetName(), handleData.first, mode);
}
void Notifier::NotifySourceProperty(const SourceImpl& source, CS_EventKind kind,
- const wpi::Twine& propertyName,
- int property, CS_PropertyKind propertyKind,
- int value, const wpi::Twine& valueStr) {
- auto thr = m_owner.GetThread();
- if (!thr) return;
-
+ std::string_view propertyName, int property,
+ CS_PropertyKind propertyKind, int value,
+ std::string_view valueStr) {
auto handleData = Instance::GetInstance().FindSource(source);
-
- thr->m_notifications.emplace(
- propertyName, handleData.first, static_cast<RawEvent::Kind>(kind),
- Handle{handleData.first, property, Handle::kProperty}, propertyKind,
- value, valueStr);
- thr->m_cond.notify_one();
+ Send(UINT_MAX, propertyName, handleData.first,
+ static_cast<RawEvent::Kind>(kind),
+ Handle{handleData.first, property, Handle::kProperty}, propertyKind,
+ value, valueStr);
}
-void Notifier::NotifySink(const wpi::Twine& name, CS_Sink sink,
+void Notifier::NotifySink(std::string_view name, CS_Sink sink,
CS_EventKind kind) {
- auto thr = m_owner.GetThread();
- if (!thr) return;
-
- thr->m_notifications.emplace(name, sink, static_cast<RawEvent::Kind>(kind));
- thr->m_cond.notify_one();
+ Send(UINT_MAX, name, sink, static_cast<RawEvent::Kind>(kind));
}
void Notifier::NotifySink(const SinkImpl& sink, CS_EventKind kind) {
@@ -203,46 +69,32 @@
NotifySink(sink.GetName(), handleData.first, kind);
}
-void Notifier::NotifySinkSourceChanged(const wpi::Twine& name, CS_Sink sink,
+void Notifier::NotifySinkSourceChanged(std::string_view name, CS_Sink sink,
CS_Source source) {
- auto thr = m_owner.GetThread();
- if (!thr) return;
-
RawEvent event{name, sink, RawEvent::kSinkSourceChanged};
event.sourceHandle = source;
-
- thr->m_notifications.emplace(std::move(event));
- thr->m_cond.notify_one();
+ Send(UINT_MAX, std::move(event));
}
void Notifier::NotifySinkProperty(const SinkImpl& sink, CS_EventKind kind,
- const wpi::Twine& propertyName, int property,
+ std::string_view propertyName, int property,
CS_PropertyKind propertyKind, int value,
- const wpi::Twine& valueStr) {
- auto thr = m_owner.GetThread();
- if (!thr) return;
-
+ std::string_view valueStr) {
auto handleData = Instance::GetInstance().FindSink(sink);
-
- thr->m_notifications.emplace(
- propertyName, handleData.first, static_cast<RawEvent::Kind>(kind),
- Handle{handleData.first, property, Handle::kSinkProperty}, propertyKind,
- value, valueStr);
- thr->m_cond.notify_one();
+ Send(UINT_MAX, propertyName, handleData.first,
+ static_cast<RawEvent::Kind>(kind),
+ Handle{handleData.first, property, Handle::kSinkProperty}, propertyKind,
+ value, valueStr);
}
void Notifier::NotifyNetworkInterfacesChanged() {
- auto thr = m_owner.GetThread();
- if (!thr) return;
-
- thr->m_notifications.emplace(RawEvent::kNetworkInterfacesChanged);
- thr->m_cond.notify_one();
+ Send(UINT_MAX, RawEvent::kNetworkInterfacesChanged);
}
void Notifier::NotifyTelemetryUpdated() {
- auto thr = m_owner.GetThread();
- if (!thr) return;
+ Send(UINT_MAX, RawEvent::kTelemetryUpdated);
+}
- thr->m_notifications.emplace(RawEvent::kTelemetryUpdated);
- thr->m_cond.notify_one();
+void Notifier::NotifyUsbCamerasChanged() {
+ Send(UINT_MAX, RawEvent::kUsbCamerasChanged);
}
diff --git a/cscore/src/main/native/cpp/Notifier.h b/cscore/src/main/native/cpp/Notifier.h
index 526cea8..c28e25c 100644
--- a/cscore/src/main/native/cpp/Notifier.h
+++ b/cscore/src/main/native/cpp/Notifier.h
@@ -1,17 +1,16 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2015-2018 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#ifndef CSCORE_NOTIFIER_H_
#define CSCORE_NOTIFIER_H_
#include <functional>
+#include <utility>
-#include <wpi/SafeThread.h>
+#include <wpi/CallbackManager.h>
+#include "Handle.h"
#include "cscore_cpp.h"
namespace cs {
@@ -19,7 +18,43 @@
class SinkImpl;
class SourceImpl;
-class Notifier {
+namespace impl {
+
+struct ListenerData : public wpi::CallbackListenerData<
+ std::function<void(const RawEvent& event)>> {
+ ListenerData() = default;
+ ListenerData(std::function<void(const RawEvent& event)> callback_,
+ int eventMask_)
+ : CallbackListenerData(std::move(callback_)), eventMask(eventMask_) {}
+ ListenerData(unsigned int pollerUid_, int eventMask_)
+ : CallbackListenerData(pollerUid_), eventMask(eventMask_) {}
+
+ int eventMask;
+};
+
+class NotifierThread
+ : public wpi::CallbackThread<NotifierThread, RawEvent, ListenerData> {
+ public:
+ NotifierThread(std::function<void()> on_start, std::function<void()> on_exit)
+ : CallbackThread(std::move(on_start), std::move(on_exit)) {}
+
+ bool Matches(const ListenerData& listener, const RawEvent& data) {
+ return (data.kind & listener.eventMask) != 0;
+ }
+
+ void SetListener(RawEvent* data, unsigned int listener_uid) {
+ data->listener = Handle(listener_uid, Handle::kListener);
+ }
+
+ void DoCallback(std::function<void(const RawEvent& event)> callback,
+ const RawEvent& data) {
+ callback(data);
+ }
+};
+
+} // namespace impl
+
+class Notifier : public wpi::CallbackManager<Notifier, impl::NotifierThread> {
friend class NotifierTest;
public:
@@ -27,44 +62,30 @@
~Notifier();
void Start();
- void Stop();
- static bool destroyed() { return s_destroyed; }
-
- void SetOnStart(std::function<void()> on_start) { m_on_start = on_start; }
- void SetOnExit(std::function<void()> on_exit) { m_on_exit = on_exit; }
-
- int AddListener(std::function<void(const RawEvent& event)> callback,
- int eventMask);
- void RemoveListener(int uid);
+ unsigned int Add(std::function<void(const RawEvent& event)> callback,
+ int eventMask);
+ unsigned int AddPolled(unsigned int pollerUid, int eventMask);
// Notification events
- void NotifySource(const wpi::Twine& name, CS_Source source,
- CS_EventKind kind);
+ void NotifySource(std::string_view name, CS_Source source, CS_EventKind kind);
void NotifySource(const SourceImpl& source, CS_EventKind kind);
void NotifySourceVideoMode(const SourceImpl& source, const VideoMode& mode);
void NotifySourceProperty(const SourceImpl& source, CS_EventKind kind,
- const wpi::Twine& propertyName, int property,
+ std::string_view propertyName, int property,
CS_PropertyKind propertyKind, int value,
- const wpi::Twine& valueStr);
- void NotifySink(const wpi::Twine& name, CS_Sink sink, CS_EventKind kind);
+ std::string_view valueStr);
+ void NotifySink(std::string_view name, CS_Sink sink, CS_EventKind kind);
void NotifySink(const SinkImpl& sink, CS_EventKind kind);
- void NotifySinkSourceChanged(const wpi::Twine& name, CS_Sink sink,
+ void NotifySinkSourceChanged(std::string_view name, CS_Sink sink,
CS_Source source);
void NotifySinkProperty(const SinkImpl& sink, CS_EventKind kind,
- const wpi::Twine& propertyName, int property,
+ std::string_view propertyName, int property,
CS_PropertyKind propertyKind, int value,
- const wpi::Twine& valueStr);
+ std::string_view valueStr);
void NotifyNetworkInterfacesChanged();
void NotifyTelemetryUpdated();
-
- private:
- class Thread;
- wpi::SafeThreadOwner<Thread> m_owner;
-
- std::function<void()> m_on_start;
- std::function<void()> m_on_exit;
- static bool s_destroyed;
+ void NotifyUsbCamerasChanged();
};
} // namespace cs
diff --git a/cscore/src/main/native/cpp/PropertyContainer.cpp b/cscore/src/main/native/cpp/PropertyContainer.cpp
index 17bf94b..b1d3a6f 100644
--- a/cscore/src/main/native/cpp/PropertyContainer.cpp
+++ b/cscore/src/main/native/cpp/PropertyContainer.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#include "PropertyContainer.h"
@@ -14,13 +11,14 @@
using namespace cs;
-int PropertyContainer::GetPropertyIndex(const wpi::Twine& name) const {
+int PropertyContainer::GetPropertyIndex(std::string_view 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);
+ if (!m_properties_cached) {
+ CacheProperties(&status);
+ }
std::scoped_lock lock(m_mutex);
- wpi::SmallVector<char, 64> nameBuf;
- int& ndx = m_properties[name.toStringRef(nameBuf)];
+ int& ndx = m_properties[name];
if (ndx == 0) {
// create a new index
ndx = m_propertyData.size() + 1;
@@ -29,41 +27,52 @@
return ndx;
}
-wpi::ArrayRef<int> PropertyContainer::EnumerateProperties(
+wpi::span<int> PropertyContainer::EnumerateProperties(
wpi::SmallVectorImpl<int>& vec, CS_Status* status) const {
- if (!m_properties_cached && !CacheProperties(status))
- return wpi::ArrayRef<int>{};
+ if (!m_properties_cached && !CacheProperties(status)) {
+ return {};
+ }
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);
+ if (m_propertyData[i]) {
+ vec.push_back(i + 1);
+ }
}
return vec;
}
CS_PropertyKind PropertyContainer::GetPropertyKind(int property) const {
CS_Status status = 0;
- if (!m_properties_cached && !CacheProperties(&status)) return CS_PROP_NONE;
+ if (!m_properties_cached && !CacheProperties(&status)) {
+ return CS_PROP_NONE;
+ }
std::scoped_lock lock(m_mutex);
auto prop = GetProperty(property);
- if (!prop) return CS_PROP_NONE;
+ if (!prop) {
+ return CS_PROP_NONE;
+ }
return prop->propKind;
}
-wpi::StringRef PropertyContainer::GetPropertyName(
+std::string_view PropertyContainer::GetPropertyName(
int property, wpi::SmallVectorImpl<char>& buf, CS_Status* status) const {
- if (!m_properties_cached && !CacheProperties(status)) return wpi::StringRef{};
+ if (!m_properties_cached && !CacheProperties(status)) {
+ return {};
+ }
std::scoped_lock lock(m_mutex);
auto prop = GetProperty(property);
if (!prop) {
*status = CS_INVALID_PROPERTY;
- return wpi::StringRef{};
+ return {};
}
// safe to not copy because we never modify it after caching
return prop->name;
}
int PropertyContainer::GetProperty(int property, CS_Status* status) const {
- if (!m_properties_cached && !CacheProperties(status)) return 0;
+ if (!m_properties_cached && !CacheProperties(status)) {
+ return 0;
+ }
std::scoped_lock lock(m_mutex);
auto prop = GetProperty(property);
if (!prop) {
@@ -88,7 +97,9 @@
}
// Guess it's integer if we've set before get
- if (prop->propKind == CS_PROP_NONE) prop->propKind = CS_PROP_INTEGER;
+ if (prop->propKind == CS_PROP_NONE) {
+ prop->propKind = CS_PROP_INTEGER;
+ }
if ((prop->propKind & (CS_PROP_BOOLEAN | CS_PROP_INTEGER | CS_PROP_ENUM)) ==
0) {
@@ -96,11 +107,13 @@
return;
}
- UpdatePropertyValue(property, false, value, wpi::Twine{});
+ UpdatePropertyValue(property, false, value, {});
}
int PropertyContainer::GetPropertyMin(int property, CS_Status* status) const {
- if (!m_properties_cached && !CacheProperties(status)) return 0;
+ if (!m_properties_cached && !CacheProperties(status)) {
+ return 0;
+ }
std::scoped_lock lock(m_mutex);
auto prop = GetProperty(property);
if (!prop) {
@@ -111,7 +124,9 @@
}
int PropertyContainer::GetPropertyMax(int property, CS_Status* status) const {
- if (!m_properties_cached && !CacheProperties(status)) return 0;
+ if (!m_properties_cached && !CacheProperties(status)) {
+ return 0;
+ }
std::scoped_lock lock(m_mutex);
auto prop = GetProperty(property);
if (!prop) {
@@ -122,7 +137,9 @@
}
int PropertyContainer::GetPropertyStep(int property, CS_Status* status) const {
- if (!m_properties_cached && !CacheProperties(status)) return 0;
+ if (!m_properties_cached && !CacheProperties(status)) {
+ return 0;
+ }
std::scoped_lock lock(m_mutex);
auto prop = GetProperty(property);
if (!prop) {
@@ -134,7 +151,9 @@
int PropertyContainer::GetPropertyDefault(int property,
CS_Status* status) const {
- if (!m_properties_cached && !CacheProperties(status)) return 0;
+ if (!m_properties_cached && !CacheProperties(status)) {
+ return 0;
+ }
std::scoped_lock lock(m_mutex);
auto prop = GetProperty(property);
if (!prop) {
@@ -144,25 +163,27 @@
return prop->defaultValue;
}
-wpi::StringRef PropertyContainer::GetStringProperty(
+std::string_view PropertyContainer::GetStringProperty(
int property, wpi::SmallVectorImpl<char>& buf, CS_Status* status) const {
- if (!m_properties_cached && !CacheProperties(status)) return wpi::StringRef{};
+ if (!m_properties_cached && !CacheProperties(status)) {
+ return {};
+ }
std::scoped_lock lock(m_mutex);
auto prop = GetProperty(property);
if (!prop) {
*status = CS_INVALID_PROPERTY;
- return wpi::StringRef{};
+ return {};
}
if (prop->propKind != CS_PROP_STRING) {
*status = CS_WRONG_PROPERTY_TYPE;
- return wpi::StringRef{};
+ return {};
}
buf.clear();
buf.append(prop->valueStr.begin(), prop->valueStr.end());
- return wpi::StringRef(buf.data(), buf.size());
+ return {buf.data(), buf.size()};
}
-void PropertyContainer::SetStringProperty(int property, const wpi::Twine& value,
+void PropertyContainer::SetStringProperty(int property, std::string_view value,
CS_Status* status) {
std::scoped_lock lock(m_mutex);
auto prop = GetProperty(property);
@@ -172,7 +193,9 @@
}
// Guess it's string if we've set before get
- if (prop->propKind == CS_PROP_NONE) prop->propKind = CS_PROP_STRING;
+ if (prop->propKind == CS_PROP_NONE) {
+ prop->propKind = CS_PROP_STRING;
+ }
if (prop->propKind != CS_PROP_STRING) {
*status = CS_WRONG_PROPERTY_TYPE;
@@ -184,23 +207,24 @@
std::vector<std::string> PropertyContainer::GetEnumPropertyChoices(
int property, CS_Status* status) const {
- if (!m_properties_cached && !CacheProperties(status))
- return std::vector<std::string>{};
+ if (!m_properties_cached && !CacheProperties(status)) {
+ return {};
+ }
std::scoped_lock lock(m_mutex);
auto prop = GetProperty(property);
if (!prop) {
*status = CS_INVALID_PROPERTY;
- return std::vector<std::string>{};
+ return {};
}
if (prop->propKind != CS_PROP_ENUM) {
*status = CS_WRONG_PROPERTY_TYPE;
- return std::vector<std::string>{};
+ return {};
}
return prop->enumChoices;
}
std::unique_ptr<PropertyImpl> PropertyContainer::CreateEmptyProperty(
- const wpi::Twine& name) const {
+ std::string_view name) const {
return std::make_unique<PropertyImpl>(name);
}
@@ -212,16 +236,15 @@
bool PropertyContainer::SetPropertiesJson(const wpi::json& config,
wpi::Logger& logger,
- wpi::StringRef logName,
+ std::string_view logName,
CS_Status* status) {
for (auto&& prop : config) {
std::string name;
try {
name = prop.at("name").get<std::string>();
} catch (const wpi::json::exception& e) {
- WPI_WARNING(logger,
- logName << ": SetConfigJson: could not read property name: "
- << e.what());
+ WPI_WARNING(logger, "{}: SetConfigJson: could not read property name: {}",
+ logName, e.what());
continue;
}
int n = GetPropertyIndex(name);
@@ -229,24 +252,24 @@
auto& v = prop.at("value");
if (v.is_string()) {
std::string val = v.get<std::string>();
- WPI_INFO(logger, logName << ": SetConfigJson: setting property '"
- << name << "' to '" << val << '\'');
+ WPI_INFO(logger, "{}: SetConfigJson: setting property '{}' to '{}'",
+ logName, name, val);
SetStringProperty(n, val, status);
} else if (v.is_boolean()) {
bool val = v.get<bool>();
- WPI_INFO(logger, logName << ": SetConfigJson: setting property '"
- << name << "' to " << val);
+ WPI_INFO(logger, "{}: SetConfigJson: setting property '{}' to {}",
+ logName, name, val);
SetProperty(n, val, status);
} else {
int val = v.get<int>();
- WPI_INFO(logger, logName << ": SetConfigJson: setting property '"
- << name << "' to " << val);
+ WPI_INFO(logger, "{}: SetConfigJson: setting property '{}' to {}",
+ logName, name, val);
SetProperty(n, val, status);
}
} catch (const wpi::json::exception& e) {
WPI_WARNING(logger,
- logName << ": SetConfigJson: could not read property value: "
- << e.what());
+ "{}: SetConfigJson: could not read property value: {}",
+ logName, e.what());
continue;
}
}
diff --git a/cscore/src/main/native/cpp/PropertyContainer.h b/cscore/src/main/native/cpp/PropertyContainer.h
index 9bbb9c7..a00c675 100644
--- a/cscore/src/main/native/cpp/PropertyContainer.h
+++ b/cscore/src/main/native/cpp/PropertyContainer.h
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#ifndef CSCORE_PROPERTYCONTAINER_H_
#define CSCORE_PROPERTYCONTAINER_H_
@@ -12,20 +9,20 @@
#include <cstddef>
#include <memory>
#include <string>
+#include <string_view>
#include <vector>
-#include <wpi/ArrayRef.h>
-#include <wpi/SmallVector.h>
#include <wpi/StringMap.h>
-#include <wpi/StringRef.h>
-#include <wpi/Twine.h>
#include <wpi/mutex.h>
+#include <wpi/span.h>
#include "PropertyImpl.h"
#include "cscore_cpp.h"
namespace wpi {
class Logger;
+template <typename T>
+class SmallVectorImpl;
class json;
} // namespace wpi
@@ -35,50 +32,54 @@
public:
virtual ~PropertyContainer() = default;
- int GetPropertyIndex(const wpi::Twine& name) const;
- wpi::ArrayRef<int> EnumerateProperties(wpi::SmallVectorImpl<int>& vec,
- CS_Status* status) const;
+ int GetPropertyIndex(std::string_view name) const;
+ wpi::span<int> EnumerateProperties(wpi::SmallVectorImpl<int>& vec,
+ CS_Status* status) const;
CS_PropertyKind GetPropertyKind(int property) const;
- wpi::StringRef GetPropertyName(int property, wpi::SmallVectorImpl<char>& buf,
- CS_Status* status) const;
+ std::string_view GetPropertyName(int property,
+ wpi::SmallVectorImpl<char>& buf,
+ CS_Status* status) const;
int GetProperty(int property, CS_Status* status) const;
virtual void SetProperty(int property, int value, CS_Status* status);
int GetPropertyMin(int property, CS_Status* status) const;
int GetPropertyMax(int property, CS_Status* status) const;
int GetPropertyStep(int property, CS_Status* status) const;
int GetPropertyDefault(int property, CS_Status* status) const;
- wpi::StringRef GetStringProperty(int property,
- wpi::SmallVectorImpl<char>& buf,
- CS_Status* status) const;
- virtual void SetStringProperty(int property, const wpi::Twine& value,
+ std::string_view GetStringProperty(int property,
+ wpi::SmallVectorImpl<char>& buf,
+ CS_Status* status) const;
+ virtual void SetStringProperty(int property, std::string_view value,
CS_Status* status);
std::vector<std::string> GetEnumPropertyChoices(int property,
CS_Status* status) const;
bool SetPropertiesJson(const wpi::json& config, wpi::Logger& logger,
- wpi::StringRef logName, CS_Status* status);
+ std::string_view logName, CS_Status* status);
wpi::json GetPropertiesJsonObject(CS_Status* status);
protected:
// Get a property; must be called with m_mutex held.
PropertyImpl* GetProperty(int property) {
- if (property <= 0 || static_cast<size_t>(property) > m_propertyData.size())
+ if (property <= 0 ||
+ static_cast<size_t>(property) > m_propertyData.size()) {
return nullptr;
+ }
return m_propertyData[property - 1].get();
}
const PropertyImpl* GetProperty(int property) const {
- if (property <= 0 || static_cast<size_t>(property) > m_propertyData.size())
+ if (property <= 0 ||
+ static_cast<size_t>(property) > m_propertyData.size()) {
return nullptr;
+ }
return m_propertyData[property - 1].get();
}
// Create or update a property; must be called with m_mutex held.
// @tparam NewFunc functor that returns a std::unique_ptr<PropertyImpl>
// @tparam UpdateFunc functor that takes a PropertyImpl&.
template <typename NewFunc, typename UpdateFunc>
- int CreateOrUpdateProperty(const wpi::Twine& name, NewFunc newFunc,
+ int CreateOrUpdateProperty(std::string_view name, NewFunc newFunc,
UpdateFunc updateFunc) {
- wpi::SmallVector<char, 64> nameBuf;
- int& ndx = m_properties[name.toStringRef(nameBuf)];
+ int& ndx = m_properties[name];
if (ndx == 0) {
// create a new index
ndx = m_propertyData.size() + 1;
@@ -90,7 +91,7 @@
return ndx;
}
template <typename NewFunc>
- int CreateProperty(const wpi::Twine& name, NewFunc newFunc) {
+ int CreateProperty(std::string_view name, NewFunc newFunc) {
return CreateOrUpdateProperty(name, newFunc, [](PropertyImpl&) {});
}
@@ -99,7 +100,7 @@
// Note: called with m_mutex held.
// The default implementation simply creates a PropertyImpl object.
virtual std::unique_ptr<PropertyImpl> CreateEmptyProperty(
- const wpi::Twine& name) const;
+ std::string_view name) const;
// Cache properties. Implementations must return false and set status to
// CS_SOURCE_IS_DISCONNECTED if not possible to cache.
@@ -110,7 +111,7 @@
// Update property value; must be called with m_mutex held.
virtual void UpdatePropertyValue(int property, bool setString, int value,
- const wpi::Twine& valueStr) = 0;
+ std::string_view valueStr) = 0;
// Whether CacheProperties() has been successful at least once (and thus
// should not be called again)
diff --git a/cscore/src/main/native/cpp/PropertyImpl.cpp b/cscore/src/main/native/cpp/PropertyImpl.cpp
index 4f1602e..3c36630 100644
--- a/cscore/src/main/native/cpp/PropertyImpl.cpp
+++ b/cscore/src/main/native/cpp/PropertyImpl.cpp
@@ -1,26 +1,23 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2018 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#include "PropertyImpl.h"
using namespace cs;
-PropertyImpl::PropertyImpl(const wpi::Twine& name_) : name{name_.str()} {}
-PropertyImpl::PropertyImpl(const wpi::Twine& name_, CS_PropertyKind kind_,
+PropertyImpl::PropertyImpl(std::string_view name_) : name{name_} {}
+PropertyImpl::PropertyImpl(std::string_view name_, CS_PropertyKind kind_,
int step_, int defaultValue_, int value_)
- : name{name_.str()},
+ : name{name_},
propKind{kind_},
step{step_},
defaultValue{defaultValue_},
value{value_} {}
-PropertyImpl::PropertyImpl(const wpi::Twine& name_, CS_PropertyKind kind_,
+PropertyImpl::PropertyImpl(std::string_view name_, CS_PropertyKind kind_,
int minimum_, int maximum_, int step_,
int defaultValue_, int value_)
- : name{name_.str()},
+ : name{name_},
propKind{kind_},
hasMinimum{true},
hasMaximum{true},
@@ -32,34 +29,39 @@
void PropertyImpl::SetValue(int v) {
int oldValue = value;
- if (hasMinimum && v < minimum)
+ if (hasMinimum && v < minimum) {
value = minimum;
- else if (hasMaximum && v > maximum)
+ } else if (hasMaximum && v > maximum) {
value = maximum;
- else
+ } else {
value = v;
+ }
bool wasValueSet = valueSet;
valueSet = true;
- if (!wasValueSet || value != oldValue) changed();
+ if (!wasValueSet || value != oldValue) {
+ changed();
+ }
}
-void PropertyImpl::SetValue(const wpi::Twine& v) {
+void PropertyImpl::SetValue(std::string_view v) {
bool valueChanged = false;
- std::string vStr = v.str();
- if (valueStr != vStr) {
- valueStr = vStr;
+ if (valueStr != v) {
+ valueStr = v;
valueChanged = true;
}
bool wasValueSet = valueSet;
valueSet = true;
- if (!wasValueSet || valueChanged) changed();
+ if (!wasValueSet || valueChanged) {
+ changed();
+ }
}
void PropertyImpl::SetDefaultValue(int v) {
- if (hasMinimum && v < minimum)
+ if (hasMinimum && v < minimum) {
defaultValue = minimum;
- else if (hasMaximum && v > maximum)
+ } else if (hasMaximum && v > maximum) {
defaultValue = maximum;
- else
+ } else {
defaultValue = v;
+ }
}
diff --git a/cscore/src/main/native/cpp/PropertyImpl.h b/cscore/src/main/native/cpp/PropertyImpl.h
index d932132..77e7908 100644
--- a/cscore/src/main/native/cpp/PropertyImpl.h
+++ b/cscore/src/main/native/cpp/PropertyImpl.h
@@ -1,19 +1,15 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2018 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#ifndef CSCORE_PROPERTYIMPL_H_
#define CSCORE_PROPERTYIMPL_H_
#include <string>
+#include <string_view>
#include <vector>
#include <wpi/Signal.h>
-#include <wpi/StringRef.h>
-#include <wpi/Twine.h>
#include "cscore_c.h"
@@ -23,17 +19,17 @@
class PropertyImpl {
public:
PropertyImpl() = default;
- explicit PropertyImpl(const wpi::Twine& name_);
- PropertyImpl(const wpi::Twine& name_, CS_PropertyKind kind_, int step_,
+ explicit PropertyImpl(std::string_view name_);
+ PropertyImpl(std::string_view name_, CS_PropertyKind kind_, int step_,
int defaultValue_, int value_);
- PropertyImpl(const wpi::Twine& name_, CS_PropertyKind kind_, int minimum_,
+ PropertyImpl(std::string_view name_, CS_PropertyKind kind_, int minimum_,
int maximum_, int step_, int defaultValue_, int value_);
virtual ~PropertyImpl() = default;
PropertyImpl(const PropertyImpl& oth) = delete;
PropertyImpl& operator=(const PropertyImpl& oth) = delete;
void SetValue(int v);
- void SetValue(const wpi::Twine& v);
+ void SetValue(std::string_view v);
void SetDefaultValue(int v);
std::string name;
diff --git a/cscore/src/main/native/cpp/RawSinkImpl.cpp b/cscore/src/main/native/cpp/RawSinkImpl.cpp
index 986378f..fbc1028 100644
--- a/cscore/src/main/native/cpp/RawSinkImpl.cpp
+++ b/cscore/src/main/native/cpp/RawSinkImpl.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#include "RawSinkImpl.h"
@@ -13,28 +10,34 @@
using namespace cs;
-RawSinkImpl::RawSinkImpl(const wpi::Twine& name, wpi::Logger& logger,
+RawSinkImpl::RawSinkImpl(std::string_view 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,
+RawSinkImpl::RawSinkImpl(std::string_view name, wpi::Logger& logger,
Notifier& notifier, Telemetry& telemetry,
std::function<void(uint64_t time)> processFrame)
: SinkImpl{name, logger, notifier, telemetry} {}
-RawSinkImpl::~RawSinkImpl() { Stop(); }
+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();
+ if (auto source = GetSource()) {
+ source->Wakeup();
+ }
// join thread
- if (m_thread.joinable()) m_thread.join();
+ if (m_thread.joinable()) {
+ m_thread.join();
+ }
}
uint64_t RawSinkImpl::GrabFrame(CS_RawFrame& image) {
@@ -124,9 +127,11 @@
std::this_thread::sleep_for(std::chrono::seconds(1));
continue;
}
- SDEBUG4("waiting for frame");
+ SDEBUG4("{}", "waiting for frame");
Frame frame = source->GetNextFrame(); // blocks
- if (!m_active) break;
+ 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));
@@ -138,14 +143,14 @@
}
namespace cs {
-CS_Sink CreateRawSink(const wpi::Twine& name, CS_Status* status) {
+CS_Sink CreateRawSink(std::string_view 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,
+CS_Sink CreateRawSinkCallback(std::string_view name,
std::function<void(uint64_t time)> processFrame,
CS_Status* status) {
auto& inst = Instance::GetInstance();
diff --git a/cscore/src/main/native/cpp/RawSinkImpl.h b/cscore/src/main/native/cpp/RawSinkImpl.h
index 3e69485..6e8032a 100644
--- a/cscore/src/main/native/cpp/RawSinkImpl.h
+++ b/cscore/src/main/native/cpp/RawSinkImpl.h
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#ifndef CSCORE_RAWSINKIMPL_H_
#define CSCORE_RAWSINKIMPL_H_
@@ -12,9 +9,9 @@
#include <atomic>
#include <functional>
+#include <string_view>
#include <thread>
-#include <wpi/Twine.h>
#include <wpi/condition_variable.h>
#include "Frame.h"
@@ -26,9 +23,9 @@
class RawSinkImpl : public SinkImpl {
public:
- RawSinkImpl(const wpi::Twine& name, wpi::Logger& logger, Notifier& notifier,
+ RawSinkImpl(std::string_view name, wpi::Logger& logger, Notifier& notifier,
Telemetry& telemetry);
- RawSinkImpl(const wpi::Twine& name, wpi::Logger& logger, Notifier& notifier,
+ RawSinkImpl(std::string_view name, wpi::Logger& logger, Notifier& notifier,
Telemetry& telemetry,
std::function<void(uint64_t time)> processFrame);
~RawSinkImpl() override;
diff --git a/cscore/src/main/native/cpp/RawSourceImpl.cpp b/cscore/src/main/native/cpp/RawSourceImpl.cpp
index e0dba2d..9ce0628 100644
--- a/cscore/src/main/native/cpp/RawSourceImpl.cpp
+++ b/cscore/src/main/native/cpp/RawSourceImpl.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#include "RawSourceImpl.h"
@@ -17,12 +14,12 @@
using namespace cs;
-RawSourceImpl::RawSourceImpl(const wpi::Twine& name, wpi::Logger& logger,
+RawSourceImpl::RawSourceImpl(std::string_view name, wpi::Logger& logger,
Notifier& notifier, Telemetry& telemetry,
const VideoMode& mode)
: ConfigurableSourceImpl{name, logger, notifier, telemetry, mode} {}
-RawSourceImpl::~RawSourceImpl() {}
+RawSourceImpl::~RawSourceImpl() = default;
void RawSourceImpl::PutFrame(const CS_RawFrame& image) {
int type;
@@ -50,7 +47,7 @@
}
namespace cs {
-CS_Source CreateRawSource(const wpi::Twine& name, const VideoMode& mode,
+CS_Source CreateRawSource(std::string_view name, const VideoMode& mode,
CS_Status* status) {
auto& inst = Instance::GetInstance();
return inst.CreateSource(CS_SOURCE_RAW, std::make_shared<RawSourceImpl>(
diff --git a/cscore/src/main/native/cpp/RawSourceImpl.h b/cscore/src/main/native/cpp/RawSourceImpl.h
index 1fdc749..5887ed4 100644
--- a/cscore/src/main/native/cpp/RawSourceImpl.h
+++ b/cscore/src/main/native/cpp/RawSourceImpl.h
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#ifndef CSCORE_RAWSOURCEIMPL_H_
#define CSCORE_RAWSOURCEIMPL_H_
@@ -12,11 +9,9 @@
#include <functional>
#include <memory>
#include <string>
+#include <string_view>
#include <vector>
-#include <wpi/ArrayRef.h>
-#include <wpi/Twine.h>
-
#include "ConfigurableSourceImpl.h"
#include "SourceImpl.h"
#include "cscore_raw.h"
@@ -25,7 +20,7 @@
class RawSourceImpl : public ConfigurableSourceImpl {
public:
- RawSourceImpl(const wpi::Twine& name, wpi::Logger& logger, Notifier& notifier,
+ RawSourceImpl(std::string_view name, wpi::Logger& logger, Notifier& notifier,
Telemetry& telemetry, const VideoMode& mode);
~RawSourceImpl() override;
diff --git a/cscore/src/main/native/cpp/SinkImpl.cpp b/cscore/src/main/native/cpp/SinkImpl.cpp
index 5d4235a..93a625f 100644
--- a/cscore/src/main/native/cpp/SinkImpl.cpp
+++ b/cscore/src/main/native/cpp/SinkImpl.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#include "SinkImpl.h"
@@ -15,36 +12,41 @@
using namespace cs;
-SinkImpl::SinkImpl(const wpi::Twine& name, wpi::Logger& logger,
+SinkImpl::SinkImpl(std::string_view name, wpi::Logger& logger,
Notifier& notifier, Telemetry& telemetry)
: m_logger(logger),
m_notifier(notifier),
m_telemetry(telemetry),
- m_name{name.str()} {}
+ m_name{name} {}
SinkImpl::~SinkImpl() {
if (m_source) {
- if (m_enabledCount > 0) m_source->DisableSink();
+ if (m_enabledCount > 0) {
+ m_source->DisableSink();
+ }
m_source->RemoveSink();
}
}
-void SinkImpl::SetDescription(const wpi::Twine& description) {
+void SinkImpl::SetDescription(std::string_view description) {
std::scoped_lock lock(m_mutex);
- m_description = description.str();
+ m_description = description;
}
-wpi::StringRef SinkImpl::GetDescription(wpi::SmallVectorImpl<char>& buf) const {
+std::string_view SinkImpl::GetDescription(
+ wpi::SmallVectorImpl<char>& buf) const {
std::scoped_lock lock(m_mutex);
buf.append(m_description.begin(), m_description.end());
- return wpi::StringRef{buf.data(), buf.size()};
+ return {buf.data(), buf.size()};
}
void SinkImpl::Enable() {
std::scoped_lock lock(m_mutex);
++m_enabledCount;
if (m_enabledCount == 1) {
- if (m_source) m_source->EnableSink();
+ if (m_source) {
+ m_source->EnableSink();
+ }
m_notifier.NotifySink(*this, CS_SINK_ENABLED);
}
}
@@ -53,7 +55,9 @@
std::scoped_lock lock(m_mutex);
--m_enabledCount;
if (m_enabledCount == 0) {
- if (m_source) m_source->DisableSink();
+ if (m_source) {
+ m_source->DisableSink();
+ }
m_notifier.NotifySink(*this, CS_SINK_DISABLED);
}
}
@@ -61,11 +65,15 @@
void SinkImpl::SetEnabled(bool enabled) {
std::scoped_lock lock(m_mutex);
if (enabled && m_enabledCount == 0) {
- if (m_source) m_source->EnableSink();
+ if (m_source) {
+ m_source->EnableSink();
+ }
m_enabledCount = 1;
m_notifier.NotifySink(*this, CS_SINK_ENABLED);
} else if (!enabled && m_enabledCount > 0) {
- if (m_source) m_source->DisableSink();
+ if (m_source) {
+ m_source->DisableSink();
+ }
m_enabledCount = 0;
m_notifier.NotifySink(*this, CS_SINK_DISABLED);
}
@@ -74,15 +82,21 @@
void SinkImpl::SetSource(std::shared_ptr<SourceImpl> source) {
{
std::scoped_lock lock(m_mutex);
- if (m_source == source) return;
+ if (m_source == source) {
+ return;
+ }
if (m_source) {
- if (m_enabledCount > 0) m_source->DisableSink();
+ if (m_enabledCount > 0) {
+ m_source->DisableSink();
+ }
m_source->RemoveSink();
}
m_source = source;
if (m_source) {
m_source->AddSink();
- if (m_enabledCount > 0) m_source->EnableSink();
+ if (m_enabledCount > 0) {
+ m_source->EnableSink();
+ }
}
}
SetSourceImpl(source);
@@ -90,27 +104,30 @@
std::string SinkImpl::GetError() const {
std::scoped_lock lock(m_mutex);
- if (!m_source) return "no source connected";
- return m_source->GetCurFrame().GetError();
+ if (!m_source) {
+ return "no source connected";
+ }
+ return std::string{m_source->GetCurFrame().GetError()};
}
-wpi::StringRef SinkImpl::GetError(wpi::SmallVectorImpl<char>& buf) const {
+std::string_view SinkImpl::GetError(wpi::SmallVectorImpl<char>& buf) const {
std::scoped_lock lock(m_mutex);
- if (!m_source) return "no source connected";
+ if (!m_source) {
+ return "no source connected";
+ }
// Make a copy as it's shared data
- wpi::StringRef error = m_source->GetCurFrame().GetError();
+ std::string_view error = m_source->GetCurFrame().GetError();
buf.clear();
buf.append(error.data(), error.data() + error.size());
- return wpi::StringRef{buf.data(), buf.size()};
+ return {buf.data(), buf.size()};
}
-bool SinkImpl::SetConfigJson(wpi::StringRef config, CS_Status* status) {
+bool SinkImpl::SetConfigJson(std::string_view config, CS_Status* status) {
wpi::json j;
try {
j = wpi::json::parse(config);
} catch (const wpi::json::parse_error& e) {
- SWARNING("SetConfigJson: parse error at byte " << e.byte << ": "
- << e.what());
+ SWARNING("SetConfigJson: parse error at byte {}: {}", e.byte, e.what());
*status = CS_PROPERTY_WRITE_FAILED;
return false;
}
@@ -118,8 +135,9 @@
}
bool SinkImpl::SetConfigJson(const wpi::json& config, CS_Status* status) {
- if (config.count("properties") != 0)
+ if (config.count("properties") != 0) {
SetPropertiesJson(config.at("properties"), m_logger, GetName(), status);
+ }
return true;
}
@@ -136,7 +154,9 @@
wpi::json j;
wpi::json props = GetPropertiesJsonObject(status);
- if (props.is_array()) j.emplace("properties", props);
+ if (props.is_array()) {
+ j.emplace("properties", props);
+ }
return j;
}
@@ -146,21 +166,25 @@
propIndex, prop.propKind, prop.value,
prop.valueStr);
// also notify choices updated event for enum types
- if (prop.propKind == CS_PROP_ENUM)
+ if (prop.propKind == CS_PROP_ENUM) {
m_notifier.NotifySinkProperty(*this, CS_SINK_PROPERTY_CHOICES_UPDATED,
prop.name, propIndex, prop.propKind,
- prop.value, wpi::Twine{});
+ prop.value, {});
+ }
}
void SinkImpl::UpdatePropertyValue(int property, bool setString, int value,
- const wpi::Twine& valueStr) {
+ std::string_view valueStr) {
auto prop = GetProperty(property);
- if (!prop) return;
+ if (!prop) {
+ return;
+ }
- if (setString)
+ if (setString) {
prop->SetValue(valueStr);
- else
+ } else {
prop->SetValue(value);
+ }
// Only notify updates after we've notified created
if (m_properties_cached) {
diff --git a/cscore/src/main/native/cpp/SinkImpl.h b/cscore/src/main/native/cpp/SinkImpl.h
index 7ad831f..aa37d61 100644
--- a/cscore/src/main/native/cpp/SinkImpl.h
+++ b/cscore/src/main/native/cpp/SinkImpl.h
@@ -1,19 +1,15 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#ifndef CSCORE_SINKIMPL_H_
#define CSCORE_SINKIMPL_H_
#include <memory>
#include <string>
+#include <string_view>
#include <wpi/Logger.h>
-#include <wpi/StringRef.h>
-#include <wpi/Twine.h>
#include <wpi/mutex.h>
#include "SourceImpl.h"
@@ -30,16 +26,16 @@
class SinkImpl : public PropertyContainer {
public:
- explicit SinkImpl(const wpi::Twine& name, wpi::Logger& logger,
+ explicit SinkImpl(std::string_view name, wpi::Logger& logger,
Notifier& notifier, Telemetry& telemetry);
- virtual ~SinkImpl();
+ ~SinkImpl() override;
SinkImpl(const SinkImpl& queue) = delete;
SinkImpl& operator=(const SinkImpl& queue) = delete;
- wpi::StringRef GetName() const { return m_name; }
+ std::string_view GetName() const { return m_name; }
- void SetDescription(const wpi::Twine& description);
- wpi::StringRef GetDescription(wpi::SmallVectorImpl<char>& buf) const;
+ void SetDescription(std::string_view description);
+ std::string_view GetDescription(wpi::SmallVectorImpl<char>& buf) const;
void Enable();
void Disable();
@@ -53,9 +49,9 @@
}
std::string GetError() const;
- wpi::StringRef GetError(wpi::SmallVectorImpl<char>& buf) const;
+ std::string_view GetError(wpi::SmallVectorImpl<char>& buf) const;
- bool SetConfigJson(wpi::StringRef config, CS_Status* status);
+ bool SetConfigJson(std::string_view config, CS_Status* status);
virtual bool SetConfigJson(const wpi::json& config, CS_Status* status);
std::string GetConfigJson(CS_Status* status);
virtual wpi::json GetConfigJsonObject(CS_Status* status);
@@ -64,7 +60,7 @@
// PropertyContainer implementation
void NotifyPropertyCreated(int propIndex, PropertyImpl& prop) override;
void UpdatePropertyValue(int property, bool setString, int value,
- const wpi::Twine& valueStr) override;
+ std::string_view valueStr) override;
virtual void SetSourceImpl(std::shared_ptr<SourceImpl> source);
diff --git a/cscore/src/main/native/cpp/SourceImpl.cpp b/cscore/src/main/native/cpp/SourceImpl.cpp
index 455b6cd..da5aa1d 100644
--- a/cscore/src/main/native/cpp/SourceImpl.cpp
+++ b/cscore/src/main/native/cpp/SourceImpl.cpp
@@ -1,15 +1,14 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#include "SourceImpl.h"
#include <algorithm>
#include <cstring>
+#include <memory>
+#include <wpi/StringExtras.h>
#include <wpi/json.h>
#include <wpi/timestamp.h>
@@ -21,13 +20,13 @@
static constexpr size_t kMaxImagesAvail = 32;
-SourceImpl::SourceImpl(const wpi::Twine& name, wpi::Logger& logger,
+SourceImpl::SourceImpl(std::string_view name, wpi::Logger& logger,
Notifier& notifier, Telemetry& telemetry)
: m_logger(logger),
m_notifier(notifier),
m_telemetry(telemetry),
- m_name{name.str()} {
- m_frame = Frame{*this, wpi::StringRef{}, 0};
+ m_name{name} {
+ m_frame = Frame{*this, std::string_view{}, 0};
}
SourceImpl::~SourceImpl() {
@@ -43,24 +42,25 @@
// Everything else can clean up itself.
}
-void SourceImpl::SetDescription(const wpi::Twine& description) {
+void SourceImpl::SetDescription(std::string_view description) {
std::scoped_lock lock(m_mutex);
- m_description = description.str();
+ m_description = description;
}
-wpi::StringRef SourceImpl::GetDescription(
+std::string_view SourceImpl::GetDescription(
wpi::SmallVectorImpl<char>& buf) const {
std::scoped_lock lock(m_mutex);
buf.append(m_description.begin(), m_description.end());
- return wpi::StringRef{buf.data(), buf.size()};
+ return {buf.data(), buf.size()};
}
void SourceImpl::SetConnected(bool connected) {
bool wasConnected = m_connected.exchange(connected);
- if (wasConnected && !connected)
+ if (wasConnected && !connected) {
m_notifier.NotifySource(*this, CS_SOURCE_DISCONNECTED);
- else if (!wasConnected && connected)
+ } else if (!wasConnected && connected) {
m_notifier.NotifySource(*this, CS_SOURCE_CONNECTED);
+ }
}
uint64_t SourceImpl::GetCurFrameTime() {
@@ -94,7 +94,7 @@
void SourceImpl::Wakeup() {
{
std::scoped_lock lock{m_frameMutex};
- m_frame = Frame{*this, wpi::StringRef{}, 0};
+ m_frame = Frame{*this, std::string_view{}, 0};
}
m_frameCv.notify_all();
}
@@ -133,7 +133,9 @@
}
VideoMode SourceImpl::GetVideoMode(CS_Status* status) const {
- if (!m_properties_cached && !CacheProperties(status)) return VideoMode{};
+ if (!m_properties_cached && !CacheProperties(status)) {
+ return {};
+ }
std::scoped_lock lock(m_mutex);
return m_mode;
}
@@ -141,14 +143,18 @@
bool SourceImpl::SetPixelFormat(VideoMode::PixelFormat pixelFormat,
CS_Status* status) {
auto mode = GetVideoMode(status);
- if (!mode) return false;
+ if (!mode) {
+ return false;
+ }
mode.pixelFormat = pixelFormat;
return SetVideoMode(mode, status);
}
bool SourceImpl::SetResolution(int width, int height, CS_Status* status) {
auto mode = GetVideoMode(status);
- if (!mode) return false;
+ if (!mode) {
+ return false;
+ }
mode.width = width;
mode.height = height;
return SetVideoMode(mode, status);
@@ -156,18 +162,19 @@
bool SourceImpl::SetFPS(int fps, CS_Status* status) {
auto mode = GetVideoMode(status);
- if (!mode) return false;
+ if (!mode) {
+ return false;
+ }
mode.fps = fps;
return SetVideoMode(mode, status);
}
-bool SourceImpl::SetConfigJson(wpi::StringRef config, CS_Status* status) {
+bool SourceImpl::SetConfigJson(std::string_view config, CS_Status* status) {
wpi::json j;
try {
j = wpi::json::parse(config);
} catch (const wpi::json::parse_error& e) {
- SWARNING("SetConfigJson: parse error at byte " << e.byte << ": "
- << e.what());
+ SWARNING("SetConfigJson: parse error at byte {}: {}", e.byte, e.what());
*status = CS_PROPERTY_WRITE_FAILED;
return false;
}
@@ -181,23 +188,22 @@
if (config.count("pixel format") != 0) {
try {
auto str = config.at("pixel format").get<std::string>();
- wpi::StringRef s(str);
- if (s.equals_lower("mjpeg")) {
+ if (wpi::equals_lower(str, "mjpeg")) {
mode.pixelFormat = cs::VideoMode::kMJPEG;
- } else if (s.equals_lower("yuyv")) {
+ } else if (wpi::equals_lower(str, "yuyv")) {
mode.pixelFormat = cs::VideoMode::kYUYV;
- } else if (s.equals_lower("rgb565")) {
+ } else if (wpi::equals_lower(str, "rgb565")) {
mode.pixelFormat = cs::VideoMode::kRGB565;
- } else if (s.equals_lower("bgr")) {
+ } else if (wpi::equals_lower(str, "bgr")) {
mode.pixelFormat = cs::VideoMode::kBGR;
- } else if (s.equals_lower("gray")) {
+ } else if (wpi::equals_lower(str, "gray")) {
mode.pixelFormat = cs::VideoMode::kGray;
} else {
- SWARNING("SetConfigJson: could not understand pixel format value '"
- << str << '\'');
+ SWARNING("SetConfigJson: could not understand pixel format value '{}'",
+ str);
}
} catch (const wpi::json::exception& e) {
- SWARNING("SetConfigJson: could not read pixel format: " << e.what());
+ SWARNING("SetConfigJson: could not read pixel format: {}", e.what());
}
}
@@ -206,7 +212,7 @@
try {
mode.width = config.at("width").get<unsigned int>();
} catch (const wpi::json::exception& e) {
- SWARNING("SetConfigJson: could not read width: " << e.what());
+ SWARNING("SetConfigJson: could not read width: {}", e.what());
}
}
@@ -215,7 +221,7 @@
try {
mode.height = config.at("height").get<unsigned int>();
} catch (const wpi::json::exception& e) {
- SWARNING("SetConfigJson: could not read height: " << e.what());
+ SWARNING("SetConfigJson: could not read height: {}", e.what());
}
}
@@ -224,30 +230,31 @@
try {
mode.fps = config.at("fps").get<unsigned int>();
} catch (const wpi::json::exception& e) {
- SWARNING("SetConfigJson: could not read fps: " << e.what());
+ SWARNING("SetConfigJson: could not read fps: {}", e.what());
}
}
// if all of video mode is set, use SetVideoMode, otherwise piecemeal it
if (mode.pixelFormat != VideoMode::kUnknown && mode.width != 0 &&
mode.height != 0 && mode.fps != 0) {
- SINFO("SetConfigJson: setting video mode to pixelFormat "
- << mode.pixelFormat << ", width " << mode.width << ", height "
- << mode.height << ", fps " << mode.fps);
+ SINFO(
+ "SetConfigJson: setting video mode to pixelFormat {}, width {}, height "
+ "{}, fps {}",
+ mode.pixelFormat, mode.width, mode.height, mode.fps);
SetVideoMode(mode, status);
} else {
if (mode.pixelFormat != cs::VideoMode::kUnknown) {
- SINFO("SetConfigJson: setting pixelFormat " << mode.pixelFormat);
+ SINFO("SetConfigJson: setting pixelFormat {}", mode.pixelFormat);
SetPixelFormat(static_cast<cs::VideoMode::PixelFormat>(mode.pixelFormat),
status);
}
if (mode.width != 0 && mode.height != 0) {
- SINFO("SetConfigJson: setting width " << mode.width << ", height "
- << mode.height);
+ SINFO("SetConfigJson: setting width {}, height {}", mode.width,
+ mode.height);
SetResolution(mode.width, mode.height, status);
}
if (mode.fps != 0) {
- SINFO("SetConfigJson: setting fps " << mode.fps);
+ SINFO("SetConfigJson: setting fps {}", mode.fps);
SetFPS(mode.fps, status);
}
}
@@ -256,10 +263,10 @@
if (config.count("brightness") != 0) {
try {
int val = config.at("brightness").get<int>();
- SINFO("SetConfigJson: setting brightness to " << val);
+ SINFO("SetConfigJson: setting brightness to {}", val);
SetBrightness(val, status);
} catch (const wpi::json::exception& e) {
- SWARNING("SetConfigJson: could not read brightness: " << e.what());
+ SWARNING("SetConfigJson: could not read brightness: {}", e.what());
}
}
@@ -269,24 +276,24 @@
auto& setting = config.at("white balance");
if (setting.is_string()) {
auto str = setting.get<std::string>();
- wpi::StringRef s(str);
- if (s.equals_lower("auto")) {
- SINFO("SetConfigJson: setting white balance to auto");
+ if (wpi::equals_lower(str, "auto")) {
+ SINFO("SetConfigJson: setting white balance to {}", "auto");
SetWhiteBalanceAuto(status);
- } else if (s.equals_lower("hold")) {
- SINFO("SetConfigJson: setting white balance to hold current");
+ } else if (wpi::equals_lower(str, "hold")) {
+ SINFO("SetConfigJson: setting white balance to {}", "hold current");
SetWhiteBalanceHoldCurrent(status);
} else {
- SWARNING("SetConfigJson: could not understand white balance value '"
- << str << '\'');
+ SWARNING(
+ "SetConfigJson: could not understand white balance value '{}'",
+ str);
}
} else {
int val = setting.get<int>();
- SINFO("SetConfigJson: setting white balance to " << val);
+ SINFO("SetConfigJson: setting white balance to {}", val);
SetWhiteBalanceManual(val, status);
}
} catch (const wpi::json::exception& e) {
- SWARNING("SetConfigJson: could not read white balance: " << e.what());
+ SWARNING("SetConfigJson: could not read white balance: {}", e.what());
}
}
@@ -296,30 +303,30 @@
auto& setting = config.at("exposure");
if (setting.is_string()) {
auto str = setting.get<std::string>();
- wpi::StringRef s(str);
- if (s.equals_lower("auto")) {
- SINFO("SetConfigJson: setting exposure to auto");
+ if (wpi::equals_lower(str, "auto")) {
+ SINFO("SetConfigJson: setting exposure to {}", "auto");
SetExposureAuto(status);
- } else if (s.equals_lower("hold")) {
- SINFO("SetConfigJson: setting exposure to hold current");
+ } else if (wpi::equals_lower(str, "hold")) {
+ SINFO("SetConfigJson: setting exposure to {}", "hold current");
SetExposureHoldCurrent(status);
} else {
- SWARNING("SetConfigJson: could not understand exposure value '"
- << str << '\'');
+ SWARNING("SetConfigJson: could not understand exposure value '{}'",
+ str);
}
} else {
int val = setting.get<int>();
- SINFO("SetConfigJson: setting exposure to " << val);
+ SINFO("SetConfigJson: setting exposure to {}", val);
SetExposureManual(val, status);
}
} catch (const wpi::json::exception& e) {
- SWARNING("SetConfigJson: could not read exposure: " << e.what());
+ SWARNING("SetConfigJson: could not read exposure: {}", e.what());
}
}
// properties
- if (config.count("properties") != 0)
+ if (config.count("properties") != 0) {
SetPropertiesJson(config.at("properties"), m_logger, GetName(), status);
+ }
return true;
}
@@ -336,7 +343,7 @@
wpi::json j;
// pixel format
- wpi::StringRef pixelFormat;
+ std::string_view pixelFormat;
switch (m_mode.pixelFormat) {
case VideoMode::kMJPEG:
pixelFormat = "mjpeg";
@@ -356,30 +363,41 @@
default:
break;
}
- if (!pixelFormat.empty()) j.emplace("pixel format", pixelFormat);
+ if (!pixelFormat.empty()) {
+ j.emplace("pixel format", pixelFormat);
+ }
// width
- if (m_mode.width != 0) j.emplace("width", m_mode.width);
+ if (m_mode.width != 0) {
+ j.emplace("width", m_mode.width);
+ }
// height
- if (m_mode.height != 0) j.emplace("height", m_mode.height);
+ if (m_mode.height != 0) {
+ j.emplace("height", m_mode.height);
+ }
// fps
- if (m_mode.fps != 0) j.emplace("fps", m_mode.fps);
+ if (m_mode.fps != 0) {
+ j.emplace("fps", m_mode.fps);
+ }
// TODO: output brightness, white balance, and exposure?
// properties
wpi::json props = GetPropertiesJsonObject(status);
- if (props.is_array()) j.emplace("properties", props);
+ if (props.is_array()) {
+ j.emplace("properties", props);
+ }
return j;
}
std::vector<VideoMode> SourceImpl::EnumerateVideoModes(
CS_Status* status) const {
- if (!m_properties_cached && !CacheProperties(status))
- return std::vector<VideoMode>{};
+ if (!m_properties_cached && !CacheProperties(status)) {
+ return {};
+ }
std::scoped_lock lock(m_mutex);
return m_videoModes;
}
@@ -404,10 +422,11 @@
}
// if nothing found, allocate a new buffer
- if (found < 0)
- image.reset(new Image{size});
- else
+ if (found < 0) {
+ image = std::make_unique<Image>(size);
+ } else {
image = std::move(m_imagesAvail[found]);
+ }
}
// Initialize image
@@ -420,14 +439,12 @@
}
void SourceImpl::PutFrame(VideoMode::PixelFormat pixelFormat, int width,
- int height, wpi::StringRef data, Frame::Time time) {
+ int height, std::string_view data, Frame::Time time) {
auto image = AllocImage(pixelFormat, width, height, data.size());
// Copy in image data
- SDEBUG4("Copying data to "
- << reinterpret_cast<const void*>(image->data()) << " from "
- << reinterpret_cast<const void*>(data.data()) << " (" << data.size()
- << " bytes)");
+ SDEBUG4("Copying data to {} from {} ({} bytes)", fmt::ptr(image->data()),
+ fmt::ptr(data.data()), data.size());
std::memcpy(image->data(), data.data(), data.size());
PutFrame(std::move(image), time);
@@ -448,7 +465,7 @@
m_frameCv.notify_all();
}
-void SourceImpl::PutError(const wpi::Twine& msg, Frame::Time time) {
+void SourceImpl::PutError(std::string_view msg, Frame::Time time) {
// Update frame
{
std::scoped_lock lock{m_frameMutex};
@@ -464,21 +481,25 @@
propIndex, prop.propKind, prop.value,
prop.valueStr);
// also notify choices updated event for enum types
- if (prop.propKind == CS_PROP_ENUM)
+ if (prop.propKind == CS_PROP_ENUM) {
m_notifier.NotifySourceProperty(*this, CS_SOURCE_PROPERTY_CHOICES_UPDATED,
prop.name, propIndex, prop.propKind,
- prop.value, wpi::Twine{});
+ prop.value, {});
+ }
}
void SourceImpl::UpdatePropertyValue(int property, bool setString, int value,
- const wpi::Twine& valueStr) {
+ std::string_view valueStr) {
auto prop = GetProperty(property);
- if (!prop) return;
+ if (!prop) {
+ return;
+ }
- if (setString)
+ if (setString) {
prop->SetValue(valueStr);
- else
+ } else {
prop->SetValue(value);
+ }
// Only notify updates after we've notified created
if (m_properties_cached) {
@@ -490,7 +511,9 @@
void SourceImpl::ReleaseImage(std::unique_ptr<Image> image) {
std::scoped_lock lock{m_poolMutex};
- if (m_destroyFrames) return;
+ if (m_destroyFrames) {
+ return;
+ }
// Return the frame to the pool. First try to find an empty slot, otherwise
// add it to the end.
auto it = std::find(m_imagesAvail.begin(), m_imagesAvail.end(), nullptr);
@@ -504,7 +527,9 @@
[](const std::unique_ptr<Image>& a, const std::unique_ptr<Image>& b) {
return a->capacity() < b->capacity();
});
- if ((*it2)->capacity() < image->capacity()) *it2 = std::move(image);
+ if ((*it2)->capacity() < image->capacity()) {
+ *it2 = std::move(image);
+ }
} else {
m_imagesAvail.emplace_back(std::move(image));
}
@@ -513,7 +538,9 @@
std::unique_ptr<Frame::Impl> SourceImpl::AllocFrameImpl() {
std::scoped_lock lock{m_poolMutex};
- if (m_framesAvail.empty()) return std::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,6 +549,8 @@
void SourceImpl::ReleaseFrameImpl(std::unique_ptr<Frame::Impl> impl) {
std::scoped_lock lock{m_poolMutex};
- if (m_destroyFrames) return;
+ if (m_destroyFrames) {
+ return;
+ }
m_framesAvail.push_back(std::move(impl));
}
diff --git a/cscore/src/main/native/cpp/SourceImpl.h b/cscore/src/main/native/cpp/SourceImpl.h
index d74d8fa..dd2e574 100644
--- a/cscore/src/main/native/cpp/SourceImpl.h
+++ b/cscore/src/main/native/cpp/SourceImpl.h
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2018 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#ifndef CSCORE_SOURCEIMPL_H_
#define CSCORE_SOURCEIMPL_H_
@@ -12,12 +9,10 @@
#include <cstddef>
#include <memory>
#include <string>
+#include <string_view>
#include <vector>
-#include <wpi/ArrayRef.h>
#include <wpi/Logger.h>
-#include <wpi/StringRef.h>
-#include <wpi/Twine.h>
#include <wpi/condition_variable.h>
#include <wpi/mutex.h>
@@ -40,18 +35,18 @@
friend class Frame;
public:
- SourceImpl(const wpi::Twine& name, wpi::Logger& logger, Notifier& notifier,
+ SourceImpl(std::string_view name, wpi::Logger& logger, Notifier& notifier,
Telemetry& telemetry);
- virtual ~SourceImpl();
+ ~SourceImpl() override;
SourceImpl(const SourceImpl& oth) = delete;
SourceImpl& operator=(const SourceImpl& oth) = delete;
virtual void Start() = 0;
- wpi::StringRef GetName() const { return m_name; }
+ std::string_view GetName() const { return m_name; }
- void SetDescription(const wpi::Twine& description);
- wpi::StringRef GetDescription(wpi::SmallVectorImpl<char>& buf) const;
+ void SetDescription(std::string_view description);
+ std::string_view GetDescription(wpi::SmallVectorImpl<char>& buf) const;
void SetConnectionStrategy(CS_ConnectionStrategy strategy) {
m_strategy = static_cast<int>(strategy);
@@ -131,7 +126,7 @@
virtual bool SetResolution(int width, int height, CS_Status* status);
virtual bool SetFPS(int fps, CS_Status* status);
- bool SetConfigJson(wpi::StringRef config, CS_Status* status);
+ bool SetConfigJson(std::string_view config, CS_Status* status);
virtual bool SetConfigJson(const wpi::json& config, CS_Status* status);
std::string GetConfigJson(CS_Status* status);
virtual wpi::json GetConfigJsonObject(CS_Status* status);
@@ -144,12 +139,12 @@
protected:
void NotifyPropertyCreated(int propIndex, PropertyImpl& prop) override;
void UpdatePropertyValue(int property, bool setString, int value,
- const wpi::Twine& valueStr) override;
+ std::string_view valueStr) override;
void PutFrame(VideoMode::PixelFormat pixelFormat, int width, int height,
- wpi::StringRef data, Frame::Time time);
+ std::string_view data, Frame::Time time);
void PutFrame(std::unique_ptr<Image> image, Frame::Time time);
- void PutError(const wpi::Twine& msg, Frame::Time time);
+ void PutError(std::string_view msg, Frame::Time time);
// Notification functions for corresponding atomics
virtual void NumSinksChanged() = 0;
diff --git a/cscore/src/main/native/cpp/Telemetry.cpp b/cscore/src/main/native/cpp/Telemetry.cpp
index 77130f6..751ef44 100644
--- a/cscore/src/main/native/cpp/Telemetry.cpp
+++ b/cscore/src/main/native/cpp/Telemetry.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#include "Telemetry.h"
@@ -25,7 +22,7 @@
public:
explicit Thread(Notifier& notifier) : m_notifier(notifier) {}
- void Main();
+ void Main() override;
Notifier& m_notifier;
wpi::DenseMap<std::pair<CS_Handle, int>, int64_t> m_user;
@@ -46,24 +43,33 @@
return it->getSecond();
}
-Telemetry::~Telemetry() {}
+Telemetry::~Telemetry() = default;
-void Telemetry::Start() { m_owner.Start(m_notifier); }
+void Telemetry::Start() {
+ m_owner.Start(m_notifier);
+}
-void Telemetry::Stop() { m_owner.Stop(); }
+void Telemetry::Stop() {
+ m_owner.Stop();
+}
void Telemetry::Thread::Main() {
std::unique_lock lock(m_mutex);
auto prevTime = std::chrono::steady_clock::now();
while (m_active) {
double period = m_period;
- if (period == 0) period = 1000.0;
+ if (period == 0) {
+ period = 1000.0;
+ }
auto timeoutTime = prevTime + std::chrono::duration<double>(period);
while (m_active && !m_updated) {
- if (m_cond.wait_until(lock, timeoutTime) == std::cv_status::timeout)
+ if (m_cond.wait_until(lock, timeoutTime) == std::cv_status::timeout) {
break;
+ }
}
- if (!m_active) break;
+ if (!m_active) {
+ break;
+ }
if (m_updated) {
m_updated = false;
continue;
@@ -83,8 +89,12 @@
void Telemetry::SetPeriod(double seconds) {
auto thr = m_owner.GetThread();
- if (!thr) return;
- if (thr->m_period == seconds) return; // no change
+ if (!thr) {
+ return;
+ }
+ if (thr->m_period == seconds) {
+ return; // no change
+ }
thr->m_period = seconds;
thr->m_updated = true;
thr->m_cond.notify_one();
@@ -92,7 +102,9 @@
double Telemetry::GetElapsedTime() {
auto thr = m_owner.GetThread();
- if (!thr) return 0;
+ if (!thr) {
+ return 0;
+ }
return thr->m_elapsed;
}
@@ -113,13 +125,17 @@
*status = CS_TELEMETRY_NOT_ENABLED;
return 0;
}
- if (thr->m_elapsed == 0) return 0.0;
+ if (thr->m_elapsed == 0) {
+ return 0.0;
+ }
return thr->GetValue(handle, kind, status) / thr->m_elapsed;
}
void Telemetry::RecordSourceBytes(const SourceImpl& source, int quantity) {
auto thr = m_owner.GetThread();
- if (!thr) return;
+ if (!thr) {
+ return;
+ }
auto handleData = Instance::GetInstance().FindSource(source);
thr->m_current[std::make_pair(Handle{handleData.first, Handle::kSource},
static_cast<int>(CS_SOURCE_BYTES_RECEIVED))] +=
@@ -128,7 +144,9 @@
void Telemetry::RecordSourceFrames(const SourceImpl& source, int quantity) {
auto thr = m_owner.GetThread();
- if (!thr) return;
+ if (!thr) {
+ return;
+ }
auto handleData = Instance::GetInstance().FindSource(source);
thr->m_current[std::make_pair(Handle{handleData.first, Handle::kSource},
static_cast<int>(CS_SOURCE_FRAMES_RECEIVED))] +=
diff --git a/cscore/src/main/native/cpp/Telemetry.h b/cscore/src/main/native/cpp/Telemetry.h
index 8729704..0a32d21 100644
--- a/cscore/src/main/native/cpp/Telemetry.h
+++ b/cscore/src/main/native/cpp/Telemetry.h
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2015-2018 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#ifndef CSCORE_TELEMETRY_H_
#define CSCORE_TELEMETRY_H_
diff --git a/cscore/src/main/native/cpp/UnlimitedHandleResource.h b/cscore/src/main/native/cpp/UnlimitedHandleResource.h
index 200572c..f7671ae 100644
--- a/cscore/src/main/native/cpp/UnlimitedHandleResource.h
+++ b/cscore/src/main/native/cpp/UnlimitedHandleResource.h
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#ifndef CSCORE_UNLIMITEDHANDLERESOURCE_H_
#define CSCORE_UNLIMITEDHANDLERESOURCE_H_
@@ -12,9 +9,9 @@
#include <utility>
#include <vector>
-#include <wpi/ArrayRef.h>
#include <wpi/SmallVector.h>
#include <wpi/mutex.h>
+#include <wpi/span.h>
namespace cs {
@@ -53,7 +50,7 @@
std::shared_ptr<TStruct> Free(THandle handle);
template <typename T>
- wpi::ArrayRef<T> GetAll(wpi::SmallVectorImpl<T>& vec);
+ wpi::span<T> GetAll(wpi::SmallVectorImpl<T>& vec);
std::vector<std::shared_ptr<TStruct>> FreeAll();
@@ -90,7 +87,9 @@
return MakeHandle(i);
}
}
- if (i >= THandle::kIndexMax) return 0;
+ if (i >= THandle::kIndexMax) {
+ return 0;
+ }
m_structures.emplace_back(
std::make_shared<TStruct>(std::forward<Args>(args)...));
@@ -108,7 +107,9 @@
return MakeHandle(i);
}
}
- if (i >= THandle::kIndexMax) return 0;
+ if (i >= THandle::kIndexMax) {
+ return 0;
+ }
m_structures.push_back(structure);
return MakeHandle(i);
@@ -120,9 +121,13 @@
THandle handle) {
auto index =
handle.GetTypedIndex(static_cast<typename THandle::Type>(typeValue));
- if (index < 0) return nullptr;
+ if (index < 0) {
+ return nullptr;
+ }
std::scoped_lock sync(m_handleMutex);
- if (index >= static_cast<int>(m_structures.size())) return nullptr;
+ if (index >= static_cast<int>(m_structures.size())) {
+ return nullptr;
+ }
return m_structures[index];
}
@@ -132,9 +137,13 @@
THandle handle) {
auto index =
handle.GetTypedIndex(static_cast<typename THandle::Type>(typeValue));
- if (index < 0) return nullptr;
+ if (index < 0) {
+ return nullptr;
+ }
std::scoped_lock sync(m_handleMutex);
- if (index >= static_cast<int>(m_structures.size())) return nullptr;
+ if (index >= static_cast<int>(m_structures.size())) {
+ return nullptr;
+ }
auto rv = std::move(m_structures[index]);
m_structures[index].reset();
return rv;
@@ -142,7 +151,7 @@
template <typename THandle, typename TStruct, int typeValue, typename TMutex>
template <typename T>
-inline wpi::ArrayRef<T>
+inline wpi::span<T>
UnlimitedHandleResource<THandle, TStruct, typeValue, TMutex>::GetAll(
wpi::SmallVectorImpl<T>& vec) {
ForEach([&](THandle handle, const TStruct& data) { vec.push_back(handle); });
@@ -164,7 +173,9 @@
UnlimitedHandleResource<THandle, TStruct, typeValue, TMutex>::ForEach(F func) {
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]));
+ if (m_structures[i] != nullptr) {
+ func(MakeHandle(i), *(m_structures[i]));
+ }
}
}
@@ -175,8 +186,9 @@
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))
+ if (structure != nullptr && func(*structure)) {
return std::make_pair(MakeHandle(i), structure);
+ }
}
return std::make_pair(0, nullptr);
}
diff --git a/cscore/src/main/native/cpp/UsbCameraImplCommon.cpp b/cscore/src/main/native/cpp/UsbCameraImplCommon.cpp
index 41906a7..5731f1f 100644
--- a/cscore/src/main/native/cpp/UsbCameraImplCommon.cpp
+++ b/cscore/src/main/native/cpp/UsbCameraImplCommon.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2020 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#include "cscore_c.h" // NOLINT(build/include_order)
@@ -19,8 +16,9 @@
out->otherPaths = static_cast<char**>(
wpi::safe_malloc(in.otherPaths.size() * sizeof(char*)));
out->otherPathsCount = in.otherPaths.size();
- for (size_t i = 0; i < in.otherPaths.size(); ++i)
+ 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;
}
@@ -28,8 +26,9 @@
static void FreeUsbCameraInfo(CS_UsbCameraInfo* info) {
std::free(info->path);
std::free(info->name);
- for (int i = 0; i < info->otherPathsCount; ++i)
+ for (int i = 0; i < info->otherPathsCount; ++i) {
std::free(info->otherPaths[i]);
+ }
std::free(info->otherPaths);
}
@@ -55,7 +54,9 @@
CS_UsbCameraInfo* CS_GetUsbCameraInfo(CS_Source source, CS_Status* status) {
auto info = cs::GetUsbCameraInfo(source, status);
- if (*status != CS_OK) return nullptr;
+ if (*status != CS_OK) {
+ return nullptr;
+ }
CS_UsbCameraInfo* out = static_cast<CS_UsbCameraInfo*>(
wpi::safe_malloc(sizeof(CS_UsbCameraInfo)));
ConvertToC(out, info);
@@ -67,18 +68,26 @@
CS_UsbCameraInfo* out = static_cast<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]);
+ for (size_t i = 0; i < cameras.size(); ++i) {
+ ConvertToC(&out[i], cameras[i]);
+ }
return out;
}
void CS_FreeEnumeratedUsbCameras(CS_UsbCameraInfo* cameras, int count) {
- if (!cameras) return;
- for (int i = 0; i < count; ++i) FreeUsbCameraInfo(&cameras[i]);
+ if (!cameras) {
+ return;
+ }
+ for (int i = 0; i < count; ++i) {
+ FreeUsbCameraInfo(&cameras[i]);
+ }
std::free(cameras);
}
void CS_FreeUsbCameraInfo(CS_UsbCameraInfo* info) {
- if (!info) return;
+ if (!info) {
+ return;
+ }
FreeUsbCameraInfo(info);
std::free(info);
}
diff --git a/cscore/src/main/native/cpp/UsbCameraListener.h b/cscore/src/main/native/cpp/UsbCameraListener.h
new file mode 100644
index 0000000..c8e8e15
--- /dev/null
+++ b/cscore/src/main/native/cpp/UsbCameraListener.h
@@ -0,0 +1,31 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+#ifndef CSCORE_USBCAMERALISTENER_H_
+#define CSCORE_USBCAMERALISTENER_H_
+
+#include <memory>
+
+#include <wpi/Logger.h>
+
+namespace cs {
+
+class Notifier;
+
+class UsbCameraListener {
+ public:
+ UsbCameraListener(wpi::Logger& logger, Notifier& notifier);
+ ~UsbCameraListener();
+
+ void Start();
+ void Stop();
+
+ private:
+ class Impl;
+ std::unique_ptr<Impl> m_impl;
+};
+
+} // namespace cs
+
+#endif // CSCORE_USBCAMERALISTENER_H_
diff --git a/cscore/src/main/native/cpp/c_util.h b/cscore/src/main/native/cpp/c_util.h
index f985fe2..904d049 100644
--- a/cscore/src/main/native/cpp/c_util.h
+++ b/cscore/src/main/native/cpp/c_util.h
@@ -1,22 +1,19 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#ifndef CSCORE_C_UTIL_H_
#define CSCORE_C_UTIL_H_
#include <cstdlib>
#include <cstring>
+#include <string_view>
#include <wpi/MemAlloc.h>
-#include <wpi/StringRef.h>
namespace cs {
-inline char* ConvertToC(wpi::StringRef in) {
+inline char* ConvertToC(std::string_view in) {
char* out = static_cast<char*>(wpi::safe_malloc(in.size() + 1));
std::memmove(out, in.data(), in.size());
out[in.size()] = '\0';
diff --git a/cscore/src/main/native/cpp/cscore_c.cpp b/cscore/src/main/native/cpp/cscore_c.cpp
index 321572e..ffbc164 100644
--- a/cscore/src/main/native/cpp/cscore_c.cpp
+++ b/cscore/src/main/native/cpp/cscore_c.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#include "cscore_c.h"
@@ -18,6 +15,39 @@
#include "cscore_cpp.h"
#include "cscore_raw.h"
+static CS_Event ConvertToC(const cs::RawEvent& rawEvent) {
+ CS_Event event;
+ event.kind = static_cast<CS_EventKind>(static_cast<int>(rawEvent.kind));
+ event.source = rawEvent.sourceHandle;
+ event.sink = rawEvent.sinkHandle;
+ event.name = rawEvent.name.c_str();
+ event.mode = rawEvent.mode;
+ event.property = rawEvent.propertyHandle;
+ event.propertyKind = rawEvent.propertyKind;
+ event.value = rawEvent.value;
+ event.valueStr = rawEvent.valueStr.c_str();
+ event.listener = rawEvent.listener;
+ return event;
+}
+
+template <typename O, typename I>
+static O* ConvertToC(std::vector<I>&& in, int* count) {
+ using T = std::vector<I>;
+ size_t size = in.size();
+ O* out = static_cast<O*>(wpi::safe_malloc(size * sizeof(O) + sizeof(T)));
+ *count = size;
+ for (size_t i = 0; i < size; ++i) {
+ out[i] = ConvertToC(in[i]);
+ }
+
+ // retain vector at end of returned array
+ alignas(T) unsigned char buf[sizeof(T)];
+ new (buf) T(std::move(in));
+ std::memcpy(out + size * sizeof(O), buf, sizeof(T));
+
+ return out;
+}
+
extern "C" {
CS_PropertyKind CS_GetPropertyKind(CS_Property property, CS_Status* status) {
@@ -27,7 +57,9 @@
char* CS_GetPropertyName(CS_Property property, CS_Status* status) {
wpi::SmallString<128> buf;
auto str = cs::GetPropertyName(property, buf, status);
- if (*status != 0) return nullptr;
+ if (*status != 0) {
+ return nullptr;
+ }
return cs::ConvertToC(str);
}
@@ -58,7 +90,9 @@
char* CS_GetStringProperty(CS_Property property, CS_Status* status) {
wpi::SmallString<128> buf;
auto str = cs::GetStringProperty(property, buf, status);
- if (*status != 0) return nullptr;
+ if (*status != 0) {
+ return nullptr;
+ }
return cs::ConvertToC(str);
}
@@ -73,8 +107,9 @@
char** out =
static_cast<char**>(wpi::safe_malloc(choices.size() * sizeof(char*)));
*count = choices.size();
- for (size_t i = 0; i < choices.size(); ++i)
+ for (size_t i = 0; i < choices.size(); ++i) {
out[i] = cs::ConvertToC(choices[i]);
+ }
return out;
}
@@ -85,14 +120,18 @@
char* CS_GetSourceName(CS_Source source, CS_Status* status) {
wpi::SmallString<128> buf;
auto str = cs::GetSourceName(source, buf, status);
- if (*status != 0) return nullptr;
+ if (*status != 0) {
+ return nullptr;
+ }
return cs::ConvertToC(str);
}
char* CS_GetSourceDescription(CS_Source source, CS_Status* status) {
wpi::SmallString<128> buf;
auto str = cs::GetSourceDescription(source, buf, status);
- if (*status != 0) return nullptr;
+ if (*status != 0) {
+ return nullptr;
+ }
return cs::ConvertToC(str);
}
@@ -251,14 +290,18 @@
char* CS_GetSinkName(CS_Sink sink, CS_Status* status) {
wpi::SmallString<128> buf;
auto str = cs::GetSinkName(sink, buf, status);
- if (*status != 0) return nullptr;
+ if (*status != 0) {
+ return nullptr;
+ }
return cs::ConvertToC(str);
}
char* CS_GetSinkDescription(CS_Sink sink, CS_Status* status) {
wpi::SmallString<128> buf;
auto str = cs::GetSinkDescription(sink, buf, status);
- if (*status != 0) return nullptr;
+ if (*status != 0) {
+ return nullptr;
+ }
return cs::ConvertToC(str);
}
@@ -309,11 +352,11 @@
}
void CS_SetListenerOnStart(void (*onStart)(void* data), void* data) {
- cs::SetListenerOnStart([=]() { onStart(data); });
+ cs::SetListenerOnStart([=] { onStart(data); });
}
void CS_SetListenerOnExit(void (*onExit)(void* data), void* data) {
- cs::SetListenerOnExit([=]() { onExit(data); });
+ cs::SetListenerOnExit([=] { onExit(data); });
}
CS_Listener CS_AddListener(void* data,
@@ -322,16 +365,7 @@
CS_Status* status) {
return cs::AddListener(
[=](const cs::RawEvent& rawEvent) {
- CS_Event event;
- event.kind = static_cast<CS_EventKind>(static_cast<int>(rawEvent.kind));
- event.source = rawEvent.sourceHandle;
- event.sink = rawEvent.sinkHandle;
- event.name = rawEvent.name.c_str();
- event.mode = rawEvent.mode;
- event.property = rawEvent.propertyHandle;
- event.propertyKind = rawEvent.propertyKind;
- event.value = rawEvent.value;
- event.valueStr = rawEvent.valueStr.c_str();
+ CS_Event event = ConvertToC(rawEvent);
callback(data, &event);
},
eventMask, immediateNotify, status);
@@ -341,9 +375,52 @@
return cs::RemoveListener(handle, status);
}
-int CS_NotifierDestroyed(void) { return cs::NotifierDestroyed(); }
+CS_ListenerPoller CS_CreateListenerPoller(void) {
+ return cs::CreateListenerPoller();
+}
-void CS_SetTelemetryPeriod(double seconds) { cs::SetTelemetryPeriod(seconds); }
+void CS_DestroyListenerPoller(CS_ListenerPoller poller) {
+ cs::DestroyListenerPoller(poller);
+}
+
+CS_Listener CS_AddPolledListener(CS_ListenerPoller poller, int eventMask,
+ CS_Bool immediateNotify, CS_Status* status) {
+ return cs::AddPolledListener(poller, eventMask, immediateNotify, status);
+}
+
+struct CS_Event* CS_PollListener(CS_ListenerPoller poller, int* count) {
+ return ConvertToC<CS_Event>(cs::PollListener(poller), count);
+}
+
+struct CS_Event* CS_PollListenerTimeout(CS_ListenerPoller poller, int* count,
+ double timeout, CS_Bool* timedOut) {
+ bool cppTimedOut = false;
+ auto arrCpp = cs::PollListener(poller, timeout, &cppTimedOut);
+ *timedOut = cppTimedOut;
+ return ConvertToC<CS_Event>(std::move(arrCpp), count);
+}
+
+void CS_CancelPollListener(CS_ListenerPoller poller) {
+ cs::CancelPollListener(poller);
+}
+
+void CS_FreeEvents(CS_Event* arr, int count) {
+ // destroy vector saved at end of array
+ using T = std::vector<cs::RawEvent>;
+ alignas(T) unsigned char buf[sizeof(T)];
+ std::memcpy(buf, arr + count * sizeof(CS_Event), sizeof(T));
+ reinterpret_cast<T*>(buf)->~T();
+
+ std::free(arr);
+}
+
+int CS_NotifierDestroyed(void) {
+ return cs::NotifierDestroyed();
+}
+
+void CS_SetTelemetryPeriod(double seconds) {
+ cs::SetTelemetryPeriod(seconds);
+}
double CS_GetTelemetryElapsedTime(void) {
return cs::GetTelemetryElapsedTime();
@@ -367,7 +444,9 @@
cs::SetDefaultLogger(min_level);
}
-void CS_Shutdown(void) { cs::Shutdown(); }
+void CS_Shutdown(void) {
+ cs::Shutdown();
+}
CS_Source* CS_EnumerateSources(int* count, CS_Status* status) {
wpi::SmallVector<CS_Source, 32> buf;
@@ -380,10 +459,14 @@
}
void CS_ReleaseEnumeratedSources(CS_Source* sources, int count) {
- if (!sources) return;
+ if (!sources) {
+ return;
+ }
for (int i = 0; i < count; ++i) {
CS_Status status = 0;
- if (sources[i] != 0) cs::ReleaseSource(sources[i], &status);
+ if (sources[i] != 0) {
+ cs::ReleaseSource(sources[i], &status);
+ }
}
std::free(sources);
}
@@ -399,19 +482,29 @@
}
void CS_ReleaseEnumeratedSinks(CS_Sink* sinks, int count) {
- if (!sinks) return;
+ if (!sinks) {
+ return;
+ }
for (int i = 0; i < count; ++i) {
CS_Status status = 0;
- if (sinks[i] != 0) cs::ReleaseSink(sinks[i], &status);
+ if (sinks[i] != 0) {
+ cs::ReleaseSink(sinks[i], &status);
+ }
}
std::free(sinks);
}
-void CS_FreeString(char* str) { std::free(str); }
+void CS_FreeString(char* str) {
+ std::free(str);
+}
void CS_FreeEnumPropertyChoices(char** choices, int count) {
- if (!choices) return;
- for (int i = 0; i < count; ++i) std::free(choices[i]);
+ if (!choices) {
+ return;
+ }
+ for (int i = 0; i < count; ++i) {
+ std::free(choices[i]);
+ }
std::free(choices);
}
@@ -423,26 +516,35 @@
std::free(modes);
}
-char* CS_GetHostname() { return cs::ConvertToC(cs::GetHostname()); }
+char* CS_GetHostname() {
+ return cs::ConvertToC(cs::GetHostname());
+}
char** CS_GetNetworkInterfaces(int* count) {
auto interfaces = cs::GetNetworkInterfaces();
char** out =
static_cast<char**>(wpi::safe_malloc(interfaces.size() * sizeof(char*)));
*count = interfaces.size();
- for (size_t i = 0; i < interfaces.size(); ++i)
+ for (size_t i = 0; i < interfaces.size(); ++i) {
out[i] = cs::ConvertToC(interfaces[i]);
+ }
return out;
}
void CS_FreeNetworkInterfaces(char** interfaces, int count) {
- if (!interfaces) return;
- for (int i = 0; i < count; ++i) std::free(interfaces[i]);
+ if (!interfaces) {
+ return;
+ }
+ for (int i = 0; i < count; ++i) {
+ std::free(interfaces[i]);
+ }
std::free(interfaces);
}
void CS_AllocateRawFrameData(CS_RawFrame* frame, int requestedSize) {
- if (frame->dataLength >= requestedSize) return;
+ if (frame->dataLength >= requestedSize) {
+ return;
+ }
if (frame->data) {
frame->data =
static_cast<char*>(wpi::safe_realloc(frame->data, requestedSize));
diff --git a/cscore/src/main/native/cpp/cscore_cpp.cpp b/cscore/src/main/native/cpp/cscore_cpp.cpp
index d49fb04..3b4e570 100644
--- a/cscore/src/main/native/cpp/cscore_cpp.cpp
+++ b/cscore/src/main/native/cpp/cscore_cpp.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#include "cscore_cpp.h"
@@ -60,7 +57,9 @@
CS_PropertyKind GetPropertyKind(CS_Property property, CS_Status* status) {
int propertyIndex;
auto container = GetPropertyContainer(property, &propertyIndex, status);
- if (!container) return CS_PROP_NONE;
+ if (!container) {
+ return CS_PROP_NONE;
+ }
return container->GetPropertyKind(propertyIndex);
}
@@ -68,58 +67,74 @@
wpi::SmallString<128> buf;
int propertyIndex;
auto container = GetPropertyContainer(property, &propertyIndex, status);
- if (!container) return std::string{};
- return container->GetPropertyName(propertyIndex, buf, status);
+ if (!container) {
+ return {};
+ }
+ return std::string{container->GetPropertyName(propertyIndex, buf, status)};
}
-wpi::StringRef GetPropertyName(CS_Property property,
- wpi::SmallVectorImpl<char>& buf,
- CS_Status* status) {
+std::string_view GetPropertyName(CS_Property property,
+ wpi::SmallVectorImpl<char>& buf,
+ CS_Status* status) {
int propertyIndex;
auto container = GetPropertyContainer(property, &propertyIndex, status);
- if (!container) return wpi::StringRef{};
+ if (!container) {
+ return {};
+ }
return container->GetPropertyName(propertyIndex, buf, status);
}
int GetProperty(CS_Property property, CS_Status* status) {
int propertyIndex;
auto container = GetPropertyContainer(property, &propertyIndex, status);
- if (!container) return false;
+ if (!container) {
+ return false;
+ }
return container->GetProperty(propertyIndex, status);
}
void SetProperty(CS_Property property, int value, CS_Status* status) {
int propertyIndex;
auto container = GetPropertyContainer(property, &propertyIndex, status);
- if (!container) return;
+ if (!container) {
+ return;
+ }
container->SetProperty(propertyIndex, value, status);
}
int GetPropertyMin(CS_Property property, CS_Status* status) {
int propertyIndex;
auto container = GetPropertyContainer(property, &propertyIndex, status);
- if (!container) return 0.0;
+ if (!container) {
+ return 0.0;
+ }
return container->GetPropertyMin(propertyIndex, status);
}
int GetPropertyMax(CS_Property property, CS_Status* status) {
int propertyIndex;
auto container = GetPropertyContainer(property, &propertyIndex, status);
- if (!container) return 0.0;
+ if (!container) {
+ return 0.0;
+ }
return container->GetPropertyMax(propertyIndex, status);
}
int GetPropertyStep(CS_Property property, CS_Status* status) {
int propertyIndex;
auto container = GetPropertyContainer(property, &propertyIndex, status);
- if (!container) return 0.0;
+ if (!container) {
+ return 0.0;
+ }
return container->GetPropertyStep(propertyIndex, status);
}
int GetPropertyDefault(CS_Property property, CS_Status* status) {
int propertyIndex;
auto container = GetPropertyContainer(property, &propertyIndex, status);
- if (!container) return 0.0;
+ if (!container) {
+ return 0.0;
+ }
return container->GetPropertyDefault(propertyIndex, status);
}
@@ -127,24 +142,30 @@
wpi::SmallString<128> buf;
int propertyIndex;
auto container = GetPropertyContainer(property, &propertyIndex, status);
- if (!container) return std::string{};
- return container->GetStringProperty(propertyIndex, buf, status);
+ if (!container) {
+ return {};
+ }
+ return std::string{container->GetStringProperty(propertyIndex, buf, status)};
}
-wpi::StringRef GetStringProperty(CS_Property property,
- wpi::SmallVectorImpl<char>& buf,
- CS_Status* status) {
+std::string_view GetStringProperty(CS_Property property,
+ wpi::SmallVectorImpl<char>& buf,
+ CS_Status* status) {
int propertyIndex;
auto container = GetPropertyContainer(property, &propertyIndex, status);
- if (!container) return wpi::StringRef{};
+ if (!container) {
+ return {};
+ }
return container->GetStringProperty(propertyIndex, buf, status);
}
-void SetStringProperty(CS_Property property, const wpi::Twine& value,
+void SetStringProperty(CS_Property property, std::string_view value,
CS_Status* status) {
int propertyIndex;
auto container = GetPropertyContainer(property, &propertyIndex, status);
- if (!container) return;
+ if (!container) {
+ return;
+ }
container->SetStringProperty(propertyIndex, value, status);
}
@@ -152,7 +173,9 @@
CS_Status* status) {
int propertyIndex;
auto container = GetPropertyContainer(property, &propertyIndex, status);
- if (!container) return std::vector<std::string>{};
+ if (!container) {
+ return {};
+ }
return container->GetEnumPropertyChoices(propertyIndex, status);
}
@@ -173,17 +196,18 @@
auto data = Instance::GetInstance().GetSource(source);
if (!data) {
*status = CS_INVALID_HANDLE;
- return std::string{};
+ return {};
}
- return data->source->GetName();
+ return std::string{data->source->GetName()};
}
-wpi::StringRef GetSourceName(CS_Source source, wpi::SmallVectorImpl<char>& buf,
- CS_Status* status) {
+std::string_view GetSourceName(CS_Source source,
+ wpi::SmallVectorImpl<char>& buf,
+ CS_Status* status) {
auto data = Instance::GetInstance().GetSource(source);
if (!data) {
*status = CS_INVALID_HANDLE;
- return wpi::StringRef{};
+ return {};
}
return data->source->GetName();
}
@@ -192,19 +216,19 @@
auto data = Instance::GetInstance().GetSource(source);
if (!data) {
*status = CS_INVALID_HANDLE;
- return std::string{};
+ return {};
}
wpi::SmallString<128> buf;
- return data->source->GetDescription(buf);
+ return std::string{data->source->GetDescription(buf)};
}
-wpi::StringRef GetSourceDescription(CS_Source source,
- wpi::SmallVectorImpl<char>& buf,
- CS_Status* status) {
+std::string_view GetSourceDescription(CS_Source source,
+ wpi::SmallVectorImpl<char>& buf,
+ CS_Status* status) {
auto data = Instance::GetInstance().GetSource(source);
if (!data) {
*status = CS_INVALID_HANDLE;
- return wpi::StringRef{};
+ return {};
}
return data->source->GetDescription(buf);
}
@@ -247,7 +271,7 @@
return data->source->IsEnabled();
}
-CS_Property GetSourceProperty(CS_Source source, const wpi::Twine& name,
+CS_Property GetSourceProperty(CS_Source source, std::string_view name,
CS_Status* status) {
auto data = Instance::GetInstance().GetSource(source);
if (!data) {
@@ -262,18 +286,19 @@
return Handle{source, property, Handle::kProperty};
}
-wpi::ArrayRef<CS_Property> EnumerateSourceProperties(
+wpi::span<CS_Property> EnumerateSourceProperties(
CS_Source source, wpi::SmallVectorImpl<CS_Property>& vec,
CS_Status* status) {
auto data = Instance::GetInstance().GetSource(source);
if (!data) {
*status = CS_INVALID_HANDLE;
- return 0;
+ return {};
}
wpi::SmallVector<int, 32> properties_buf;
for (auto property :
- data->source->EnumerateProperties(properties_buf, status))
+ data->source->EnumerateProperties(properties_buf, status)) {
vec.push_back(Handle{source, property, Handle::kProperty});
+ }
return vec;
}
@@ -325,7 +350,7 @@
return data->source->SetFPS(fps, status);
}
-bool SetSourceConfigJson(CS_Source source, wpi::StringRef config,
+bool SetSourceConfigJson(CS_Source source, std::string_view config,
CS_Status* status) {
auto data = Instance::GetInstance().GetSource(source);
if (!data) {
@@ -373,20 +398,22 @@
return data->source->EnumerateVideoModes(status);
}
-wpi::ArrayRef<CS_Sink> EnumerateSourceSinks(CS_Source source,
- wpi::SmallVectorImpl<CS_Sink>& vec,
- CS_Status* status) {
+wpi::span<CS_Sink> EnumerateSourceSinks(CS_Source source,
+ wpi::SmallVectorImpl<CS_Sink>& vec,
+ CS_Status* status) {
auto& inst = Instance::GetInstance();
auto data = inst.GetSource(source);
if (!data) {
*status = CS_INVALID_HANDLE;
- return wpi::ArrayRef<CS_Sink>{};
+ return {};
}
return inst.EnumerateSourceSinks(source, vec);
}
CS_Source CopySource(CS_Source source, CS_Status* status) {
- if (source == 0) return 0;
+ if (source == 0) {
+ return 0;
+ }
auto data = Instance::GetInstance().GetSource(source);
if (!data) {
*status = CS_INVALID_HANDLE;
@@ -397,14 +424,18 @@
}
void ReleaseSource(CS_Source source, CS_Status* status) {
- if (source == 0) return;
+ if (source == 0) {
+ return;
+ }
auto& inst = Instance::GetInstance();
auto data = inst.GetSource(source);
if (!data) {
*status = CS_INVALID_HANDLE;
return;
}
- if (data->refCount-- == 0) inst.DestroySource(source);
+ if (data->refCount-- == 0) {
+ inst.DestroySource(source);
+ }
}
//
@@ -501,17 +532,17 @@
auto data = Instance::GetInstance().GetSink(sink);
if (!data) {
*status = CS_INVALID_HANDLE;
- return std::string{};
+ return {};
}
- return data->sink->GetName();
+ return std::string{data->sink->GetName()};
}
-wpi::StringRef GetSinkName(CS_Sink sink, wpi::SmallVectorImpl<char>& buf,
- CS_Status* status) {
+std::string_view GetSinkName(CS_Sink sink, wpi::SmallVectorImpl<char>& buf,
+ CS_Status* status) {
auto data = Instance::GetInstance().GetSink(sink);
if (!data) {
*status = CS_INVALID_HANDLE;
- return wpi::StringRef{};
+ return {};
}
return data->sink->GetName();
}
@@ -520,23 +551,24 @@
auto data = Instance::GetInstance().GetSink(sink);
if (!data) {
*status = CS_INVALID_HANDLE;
- return std::string{};
+ return {};
}
wpi::SmallString<128> buf;
- return data->sink->GetDescription(buf);
+ return std::string{data->sink->GetDescription(buf)};
}
-wpi::StringRef GetSinkDescription(CS_Sink sink, wpi::SmallVectorImpl<char>& buf,
- CS_Status* status) {
+std::string_view GetSinkDescription(CS_Sink sink,
+ wpi::SmallVectorImpl<char>& buf,
+ CS_Status* status) {
auto data = Instance::GetInstance().GetSink(sink);
if (!data) {
*status = CS_INVALID_HANDLE;
- return wpi::StringRef{};
+ return {};
}
return data->sink->GetDescription(buf);
}
-CS_Property GetSinkProperty(CS_Sink sink, const wpi::Twine& name,
+CS_Property GetSinkProperty(CS_Sink sink, std::string_view name,
CS_Status* status) {
auto data = Instance::GetInstance().GetSink(sink);
if (!data) {
@@ -551,20 +583,23 @@
return Handle{sink, property, Handle::kSinkProperty};
}
-wpi::ArrayRef<CS_Property> EnumerateSinkProperties(
+wpi::span<CS_Property> EnumerateSinkProperties(
CS_Sink sink, wpi::SmallVectorImpl<CS_Property>& vec, CS_Status* status) {
auto data = Instance::GetInstance().GetSink(sink);
if (!data) {
*status = CS_INVALID_HANDLE;
- return 0;
+ return {};
}
wpi::SmallVector<int, 32> properties_buf;
- for (auto property : data->sink->EnumerateProperties(properties_buf, status))
+ for (auto property :
+ data->sink->EnumerateProperties(properties_buf, status)) {
vec.push_back(Handle{sink, property, Handle::kSinkProperty});
+ }
return vec;
}
-bool SetSinkConfigJson(CS_Sink sink, wpi::StringRef config, CS_Status* status) {
+bool SetSinkConfigJson(CS_Sink sink, std::string_view config,
+ CS_Status* status) {
auto data = Instance::GetInstance().GetSink(sink);
if (!data) {
*status = CS_INVALID_HANDLE;
@@ -631,7 +666,7 @@
return data->sourceHandle.load();
}
-CS_Property GetSinkSourceProperty(CS_Sink sink, const wpi::Twine& name,
+CS_Property GetSinkSourceProperty(CS_Sink sink, std::string_view name,
CS_Status* status) {
auto data = Instance::GetInstance().GetSink(sink);
if (!data) {
@@ -642,7 +677,9 @@
}
CS_Sink CopySink(CS_Sink sink, CS_Status* status) {
- if (sink == 0) return 0;
+ if (sink == 0) {
+ return 0;
+ }
auto data = Instance::GetInstance().GetSink(sink);
if (!data) {
*status = CS_INVALID_HANDLE;
@@ -653,14 +690,18 @@
}
void ReleaseSink(CS_Sink sink, CS_Status* status) {
- if (sink == 0) return;
+ if (sink == 0) {
+ return;
+ }
auto& inst = Instance::GetInstance();
auto data = inst.GetSink(sink);
if (!data) {
*status = CS_INVALID_HANDLE;
return;
}
- if (data->refCount-- == 0) inst.DestroySink(sink);
+ if (data->refCount-- == 0) {
+ inst.DestroySink(sink);
+ }
}
//
@@ -675,16 +716,30 @@
Instance::GetInstance().notifier.SetOnExit(onExit);
}
+static void StartBackground(int eventMask, bool immediateNotify) {
+ auto& inst = Instance::GetInstance();
+ if ((eventMask & CS_NETWORK_INTERFACES_CHANGED) != 0) {
+ // start network interface event listener
+ inst.networkListener.Start();
+ if (immediateNotify) {
+ inst.notifier.NotifyNetworkInterfacesChanged();
+ }
+ }
+ if ((eventMask & CS_USB_CAMERAS_CHANGED) != 0) {
+ // start network interface event listener
+ inst.usbCameraListener.Start();
+ if (immediateNotify) {
+ inst.notifier.NotifyUsbCamerasChanged();
+ }
+ }
+}
+
CS_Listener AddListener(std::function<void(const RawEvent& event)> callback,
int eventMask, bool immediateNotify,
CS_Status* status) {
auto& inst = Instance::GetInstance();
- int uid = inst.notifier.AddListener(callback, eventMask);
- if ((eventMask & CS_NETWORK_INTERFACES_CHANGED) != 0) {
- // start network interface event listener
- inst.networkListener.Start();
- if (immediateNotify) inst.notifier.NotifyNetworkInterfacesChanged();
- }
+ int uid = inst.notifier.Add(callback, eventMask);
+ StartBackground(eventMask, immediateNotify);
if (immediateNotify) {
// TODO
}
@@ -697,10 +752,68 @@
*status = CS_INVALID_HANDLE;
return;
}
- Instance::GetInstance().notifier.RemoveListener(uid);
+ Instance::GetInstance().notifier.Remove(uid);
}
-bool NotifierDestroyed() { return Notifier::destroyed(); }
+CS_ListenerPoller CreateListenerPoller() {
+ auto& inst = Instance::GetInstance();
+ return Handle(inst.notifier.CreatePoller(), Handle::kListenerPoller);
+}
+
+void DestroyListenerPoller(CS_ListenerPoller poller) {
+ int uid = Handle{poller}.GetTypedIndex(Handle::kListenerPoller);
+ if (uid < 0) {
+ return;
+ }
+ Instance::GetInstance().notifier.RemovePoller(uid);
+}
+
+CS_Listener AddPolledListener(CS_ListenerPoller poller, int eventMask,
+ bool immediateNotify, CS_Status* status) {
+ Handle handle{poller};
+ int id = handle.GetTypedIndex(Handle::kListenerPoller);
+ if (id < 0) {
+ *status = CS_INVALID_HANDLE;
+ return 0;
+ }
+
+ auto& inst = Instance::GetInstance();
+ int uid = inst.notifier.AddPolled(id, eventMask);
+ StartBackground(eventMask, immediateNotify);
+ return Handle{uid, Handle::kListener};
+}
+
+std::vector<RawEvent> PollListener(CS_ListenerPoller poller) {
+ Handle handle{poller};
+ int id = handle.GetTypedIndex(Handle::kListenerPoller);
+ if (id < 0) {
+ return {};
+ }
+ return Instance::GetInstance().notifier.Poll(id);
+}
+
+std::vector<RawEvent> PollListener(CS_ListenerPoller poller, double timeout,
+ bool* timedOut) {
+ Handle handle{poller};
+ int id = handle.GetTypedIndex(Handle::kListenerPoller);
+ if (id < 0) {
+ return {};
+ }
+ return Instance::GetInstance().notifier.Poll(id, timeout, timedOut);
+}
+
+void CancelPollListener(CS_ListenerPoller poller) {
+ Handle handle{poller};
+ int id = handle.GetTypedIndex(Handle::kListenerPoller);
+ if (id < 0) {
+ return;
+ }
+ return Instance::GetInstance().notifier.CancelPoll(id);
+}
+
+bool NotifierDestroyed() {
+ return false;
+}
//
// Telemetry Functions
@@ -744,22 +857,26 @@
//
// Shutdown Function
//
-void Shutdown() { Instance::GetInstance().Shutdown(); }
+void Shutdown() {
+ Instance::GetInstance().Shutdown();
+}
//
// Utility Functions
//
-wpi::ArrayRef<CS_Source> EnumerateSourceHandles(
+wpi::span<CS_Source> EnumerateSourceHandles(
wpi::SmallVectorImpl<CS_Source>& vec, CS_Status* status) {
return Instance::GetInstance().EnumerateSourceHandles(vec);
}
-wpi::ArrayRef<CS_Sink> EnumerateSinkHandles(wpi::SmallVectorImpl<CS_Sink>& vec,
- CS_Status* status) {
+wpi::span<CS_Sink> EnumerateSinkHandles(wpi::SmallVectorImpl<CS_Sink>& vec,
+ CS_Status* status) {
return Instance::GetInstance().EnumerateSinkHandles(vec);
}
-std::string GetHostname() { return wpi::GetHostname(); }
+std::string GetHostname() {
+ return wpi::GetHostname();
+}
} // namespace cs
diff --git a/cscore/src/main/native/cpp/cscore_oo.cpp b/cscore/src/main/native/cpp/cscore_oo.cpp
index f42ed5a..cca5ba7 100644
--- a/cscore/src/main/native/cpp/cscore_oo.cpp
+++ b/cscore/src/main/native/cpp/cscore_oo.cpp
@@ -1,12 +1,10 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#include "cscore_oo.h"
+#include <fmt/format.h>
#include <wpi/json.h>
using namespace cs;
@@ -28,8 +26,9 @@
std::vector<VideoProperty> properties;
properties.reserve(handles.size());
- for (CS_Property handle : handles)
+ for (CS_Property handle : handles) {
properties.emplace_back(VideoProperty{handle});
+ }
return properties;
}
@@ -40,7 +39,9 @@
std::vector<VideoSink> sinks;
sinks.reserve(handles.size());
- for (int handle : handles) sinks.emplace_back(VideoSink{handle});
+ for (int handle : handles) {
+ sinks.emplace_back(VideoSink{handle});
+ }
return sinks;
}
@@ -51,7 +52,9 @@
std::vector<VideoSource> sources;
sources.reserve(handles.size());
- for (int handle : handles) sources.emplace_back(VideoSource{handle});
+ for (int handle : handles) {
+ sources.emplace_back(VideoSource{handle});
+ }
return sources;
}
@@ -62,8 +65,9 @@
std::vector<VideoProperty> properties;
properties.reserve(handles.size());
- for (CS_Property handle : handles)
+ for (CS_Property handle : handles) {
properties.emplace_back(VideoProperty{handle});
+ }
return properties;
}
@@ -74,6 +78,12 @@
std::vector<VideoSink> sinks;
sinks.reserve(handles.size());
- for (int handle : handles) sinks.emplace_back(VideoSink{handle});
+ for (int handle : handles) {
+ sinks.emplace_back(VideoSink{handle});
+ }
return sinks;
}
+
+std::string AxisCamera::HostToUrl(std::string_view host) {
+ return fmt::format("http://{}/mjpg/video.mjpg", host);
+}
diff --git a/cscore/src/main/native/cpp/jni/CameraServerJNI.cpp b/cscore/src/main/native/cpp/jni/CameraServerJNI.cpp
index e9408fd..b99d322 100644
--- a/cscore/src/main/native/cpp/jni/CameraServerJNI.cpp
+++ b/cscore/src/main/native/cpp/jni/CameraServerJNI.cpp
@@ -1,21 +1,19 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2020 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#include <exception>
+#include <fmt/format.h>
#include <opencv2/core/core.hpp>
#include <wpi/SmallString.h>
#include <wpi/jni_util.h>
-#include <wpi/raw_ostream.h>
+#include <wpi/span.h>
#include "cscore_cpp.h"
#include "cscore_cv.h"
#include "cscore_raw.h"
-#include "edu_wpi_cscore_CameraServerJNI.h"
+#include "edu_wpi_first_cscore_CameraServerJNI.h"
namespace cv {
class Mat;
@@ -34,6 +32,7 @@
static JClass videoEventCls;
static JClass rawFrameCls;
static JException videoEx;
+static JException interruptedEx;
static JException nullPointerEx;
static JException unsupportedEx;
static JException exceptionEx;
@@ -41,41 +40,49 @@
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/raw/RawFrame", &rawFrameCls}};
+ {"edu/wpi/first/cscore/UsbCameraInfo", &usbCameraInfoCls},
+ {"edu/wpi/first/cscore/VideoMode", &videoModeCls},
+ {"edu/wpi/first/cscore/VideoEvent", &videoEventCls},
+ {"edu/wpi/first/cscore/raw/RawFrame", &rawFrameCls}};
static const JExceptionInit exceptions[] = {
- {"edu/wpi/cscore/VideoException", &videoEx},
+ {"edu/wpi/first/cscore/VideoException", &videoEx},
+ {"java/lang/InterruptedException", &interruptedEx},
{"java/lang/NullPointerException", &nullPointerEx},
{"java/lang/UnsupportedOperationException", &unsupportedEx},
{"java/lang/Exception", &exceptionEx}};
static void ListenerOnStart() {
- if (!jvm) return;
+ if (!jvm) {
+ return;
+ }
JNIEnv* env;
JavaVMAttachArgs args;
args.version = JNI_VERSION_1_2;
args.name = const_cast<char*>("CSListener");
args.group = nullptr;
if (jvm->AttachCurrentThreadAsDaemon(reinterpret_cast<void**>(&env), &args) !=
- JNI_OK)
+ JNI_OK) {
return;
- if (!env || !env->functions) return;
+ }
+ if (!env || !env->functions) {
+ return;
+ }
listenerEnv = env;
}
static void ListenerOnExit() {
listenerEnv = nullptr;
- if (!jvm) return;
+ if (!jvm) {
+ return;
+ }
jvm->DetachCurrentThread();
}
/// throw java exception
static void ThrowJavaException(JNIEnv* env, const std::exception* e) {
wpi::SmallString<128> what;
- jclass je = 0;
+ jclass je = nullptr;
if (e) {
const char* exception_type = "std::exception";
@@ -92,7 +99,9 @@
what = "unknown exception";
}
- if (!je) je = exceptionEx;
+ if (!je) {
+ je = exceptionEx;
+ }
env->ThrowNew(je, what.c_str());
}
@@ -102,18 +111,23 @@
jvm = vm;
JNIEnv* env;
- if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK)
+ if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
return JNI_ERR;
+ }
// Cache references to classes
for (auto& c : classes) {
*c.cls = JClass(env, c.name);
- if (!*c.cls) return JNI_ERR;
+ if (!*c.cls) {
+ return JNI_ERR;
+ }
}
for (auto& c : exceptions) {
*c.cls = JException(env, c.name);
- if (!*c.cls) return JNI_ERR;
+ if (!*c.cls) {
+ return JNI_ERR;
+ }
}
// Initial configuration of listener start/exit
@@ -127,8 +141,9 @@
cs::Shutdown();
JNIEnv* env;
- if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK)
+ if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
return;
+ }
// Delete global references
for (auto& c : classes) {
c.cls->free(env);
@@ -150,22 +165,29 @@
JCSGlobal(JNIEnv* env, T obj)
: m_obj(static_cast<T>(env->NewGlobalRef(obj))) {}
~JCSGlobal() {
- if (!jvm || cs::NotifierDestroyed()) return;
+ if (!jvm || cs::NotifierDestroyed()) {
+ return;
+ }
JNIEnv* env;
bool attached = false;
// don't attach and de-attach if already attached to a thread.
if (jvm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) ==
JNI_EDETACHED) {
if (jvm->AttachCurrentThread(reinterpret_cast<void**>(&env), nullptr) !=
- JNI_OK)
+ JNI_OK) {
return;
+ }
attached = true;
}
- if (!env || !env->functions) return;
+ if (!env || !env->functions) {
+ return;
+ }
env->DeleteGlobalRef(m_obj);
- if (attached) jvm->DetachCurrentThread();
+ if (attached) {
+ jvm->DetachCurrentThread();
+ }
}
- operator T() { return m_obj; }
+ operator T() { return m_obj; } // NOLINT
T obj() { return m_obj; }
private:
@@ -173,8 +195,11 @@
};
static void ReportError(JNIEnv* env, CS_Status status) {
- if (status == CS_OK) return;
- wpi::SmallString<64> msg;
+ if (status == CS_OK) {
+ return;
+ }
+ std::string_view msg;
+ std::string msgBuf;
switch (status) {
case CS_PROPERTY_WRITE_FAILED:
msg = "property write failed";
@@ -207,8 +232,8 @@
msg = "telemetry not enabled";
break;
default: {
- wpi::raw_svector_ostream oss{msg};
- oss << "unknown error code=" << status;
+ msgBuf = fmt::format("unknown error code={}", status);
+ msg = msgBuf;
break;
}
}
@@ -216,7 +241,9 @@
}
static inline bool CheckStatus(JNIEnv* env, CS_Status status) {
- if (status != CS_OK) ReportError(env, status);
+ if (status != CS_OK) {
+ ReportError(env, status);
+ }
return status == CS_OK;
}
@@ -245,7 +272,7 @@
static jobject MakeJObject(JNIEnv* env, const cs::RawEvent& event) {
static jmethodID constructor =
env->GetMethodID(videoEventCls, "<init>",
- "(IIILjava/lang/String;IIIIIIILjava/lang/String;)V");
+ "(IIILjava/lang/String;IIIIIIILjava/lang/String;I)V");
JLocal<jstring> name(env, MakeJString(env, event.name));
JLocal<jstring> valueStr(env, MakeJString(env, event.valueStr));
// clang-format off
@@ -263,19 +290,33 @@
static_cast<jint>(event.propertyHandle),
static_cast<jint>(event.propertyKind),
static_cast<jint>(event.value),
- valueStr.obj());
+ valueStr.obj(),
+ static_cast<jint>(event.listener));
// clang-format on
}
+static jobjectArray MakeJObject(JNIEnv* env,
+ wpi::span<const cs::RawEvent> arr) {
+ jobjectArray jarr = env->NewObjectArray(arr.size(), videoEventCls, nullptr);
+ if (!jarr) {
+ return nullptr;
+ }
+ for (size_t i = 0; i < arr.size(); ++i) {
+ JLocal<jobject> elem{env, MakeJObject(env, arr[i])};
+ env->SetObjectArrayElement(jarr, i, elem.obj());
+ }
+ return jarr;
+}
+
extern "C" {
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: getPropertyKind
* Signature: (I)I
*/
JNIEXPORT jint JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_getPropertyKind
+Java_edu_wpi_first_cscore_CameraServerJNI_getPropertyKind
(JNIEnv* env, jclass, jint property)
{
CS_Status status = 0;
@@ -285,28 +326,30 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: getPropertyName
* Signature: (I)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_getPropertyName
+Java_edu_wpi_first_cscore_CameraServerJNI_getPropertyName
(JNIEnv* env, jclass, jint property)
{
CS_Status status = 0;
wpi::SmallString<128> buf;
auto str = cs::GetPropertyName(property, buf, &status);
- if (!CheckStatus(env, status)) return nullptr;
+ if (!CheckStatus(env, status)) {
+ return nullptr;
+ }
return MakeJString(env, str);
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: getProperty
* Signature: (I)I
*/
JNIEXPORT jint JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_getProperty
+Java_edu_wpi_first_cscore_CameraServerJNI_getProperty
(JNIEnv* env, jclass, jint property)
{
CS_Status status = 0;
@@ -316,12 +359,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: setProperty
* Signature: (II)V
*/
JNIEXPORT void JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_setProperty
+Java_edu_wpi_first_cscore_CameraServerJNI_setProperty
(JNIEnv* env, jclass, jint property, jint value)
{
CS_Status status = 0;
@@ -330,12 +373,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: getPropertyMin
* Signature: (I)I
*/
JNIEXPORT jint JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_getPropertyMin
+Java_edu_wpi_first_cscore_CameraServerJNI_getPropertyMin
(JNIEnv* env, jclass, jint property)
{
CS_Status status = 0;
@@ -345,12 +388,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: getPropertyMax
* Signature: (I)I
*/
JNIEXPORT jint JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_getPropertyMax
+Java_edu_wpi_first_cscore_CameraServerJNI_getPropertyMax
(JNIEnv* env, jclass, jint property)
{
CS_Status status = 0;
@@ -360,12 +403,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: getPropertyStep
* Signature: (I)I
*/
JNIEXPORT jint JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_getPropertyStep
+Java_edu_wpi_first_cscore_CameraServerJNI_getPropertyStep
(JNIEnv* env, jclass, jint property)
{
CS_Status status = 0;
@@ -375,12 +418,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: getPropertyDefault
* Signature: (I)I
*/
JNIEXPORT jint JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_getPropertyDefault
+Java_edu_wpi_first_cscore_CameraServerJNI_getPropertyDefault
(JNIEnv* env, jclass, jint property)
{
CS_Status status = 0;
@@ -390,28 +433,30 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: getStringProperty
* Signature: (I)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_getStringProperty
+Java_edu_wpi_first_cscore_CameraServerJNI_getStringProperty
(JNIEnv* env, jclass, jint property)
{
CS_Status status = 0;
wpi::SmallString<128> buf;
auto str = cs::GetStringProperty(property, buf, &status);
- if (!CheckStatus(env, status)) return nullptr;
+ if (!CheckStatus(env, status)) {
+ return nullptr;
+ }
return MakeJString(env, str);
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: setStringProperty
* Signature: (ILjava/lang/String;)V
*/
JNIEXPORT void JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_setStringProperty
+Java_edu_wpi_first_cscore_CameraServerJNI_setStringProperty
(JNIEnv* env, jclass, jint property, jstring value)
{
if (!value) {
@@ -424,27 +469,29 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: getEnumPropertyChoices
* Signature: (I)[Ljava/lang/Object;
*/
JNIEXPORT jobjectArray JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_getEnumPropertyChoices
+Java_edu_wpi_first_cscore_CameraServerJNI_getEnumPropertyChoices
(JNIEnv* env, jclass, jint property)
{
CS_Status status = 0;
auto arr = cs::GetEnumPropertyChoices(property, &status);
- if (!CheckStatus(env, status)) return nullptr;
+ if (!CheckStatus(env, status)) {
+ return nullptr;
+ }
return MakeJStringArray(env, arr);
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: createUsbCameraDev
* Signature: (Ljava/lang/String;I)I
*/
JNIEXPORT jint JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_createUsbCameraDev
+Java_edu_wpi_first_cscore_CameraServerJNI_createUsbCameraDev
(JNIEnv* env, jclass, jstring name, jint dev)
{
if (!name) {
@@ -458,12 +505,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: createUsbCameraPath
* Signature: (Ljava/lang/String;Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_createUsbCameraPath
+Java_edu_wpi_first_cscore_CameraServerJNI_createUsbCameraPath
(JNIEnv* env, jclass, jstring name, jstring path)
{
if (!name) {
@@ -482,12 +529,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: createHttpCamera
* Signature: (Ljava/lang/String;Ljava/lang/String;I)I
*/
JNIEXPORT jint JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_createHttpCamera
+Java_edu_wpi_first_cscore_CameraServerJNI_createHttpCamera
(JNIEnv* env, jclass, jstring name, jstring url, jint kind)
{
if (!name) {
@@ -507,12 +554,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: createHttpCameraMulti
* Signature: (Ljava/lang/String;[Ljava/lang/Object;I)I
*/
JNIEXPORT jint JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_createHttpCameraMulti
+Java_edu_wpi_first_cscore_CameraServerJNI_createHttpCameraMulti
(JNIEnv* env, jclass, jstring name, jobjectArray urls, jint kind)
{
if (!name) {
@@ -533,7 +580,7 @@
// TODO
return 0;
}
- vec.push_back(JStringRef{env, elem}.str());
+ vec.emplace_back(JStringRef{env, elem}.str());
}
CS_Status status = 0;
auto val =
@@ -544,12 +591,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerCvJNI
+ * Class: edu_wpi_first_cscore_CameraServerCvJNI
* Method: createCvSource
* Signature: (Ljava/lang/String;IIII)I
*/
JNIEXPORT jint JNICALL
-Java_edu_wpi_cscore_CameraServerCvJNI_createCvSource
+Java_edu_wpi_first_cscore_CameraServerCvJNI_createCvSource
(JNIEnv* env, jclass, jstring name, jint pixelFormat, jint width, jint height,
jint fps)
{
@@ -569,12 +616,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: createRawSource
* Signature: (Ljava/lang/String;IIII)I
*/
JNIEXPORT jint JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_createRawSource
+Java_edu_wpi_first_cscore_CameraServerJNI_createRawSource
(JNIEnv* env, jclass, jstring name, jint pixelFormat, jint width, jint height,
jint fps)
{
@@ -594,12 +641,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: getSourceKind
* Signature: (I)I
*/
JNIEXPORT jint JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_getSourceKind
+Java_edu_wpi_first_cscore_CameraServerJNI_getSourceKind
(JNIEnv* env, jclass, jint source)
{
CS_Status status = 0;
@@ -609,44 +656,48 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: getSourceName
* Signature: (I)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_getSourceName
+Java_edu_wpi_first_cscore_CameraServerJNI_getSourceName
(JNIEnv* env, jclass, jint source)
{
CS_Status status = 0;
wpi::SmallString<128> buf;
auto str = cs::GetSourceName(source, buf, &status);
- if (!CheckStatus(env, status)) return nullptr;
+ if (!CheckStatus(env, status)) {
+ return nullptr;
+ }
return MakeJString(env, str);
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: getSourceDescription
* Signature: (I)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_getSourceDescription
+Java_edu_wpi_first_cscore_CameraServerJNI_getSourceDescription
(JNIEnv* env, jclass, jint source)
{
CS_Status status = 0;
wpi::SmallString<128> buf;
auto str = cs::GetSourceDescription(source, buf, &status);
- if (!CheckStatus(env, status)) return nullptr;
+ if (!CheckStatus(env, status)) {
+ return nullptr;
+ }
return MakeJString(env, str);
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: getSourceLastFrameTime
* Signature: (I)J
*/
JNIEXPORT jlong JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_getSourceLastFrameTime
+Java_edu_wpi_first_cscore_CameraServerJNI_getSourceLastFrameTime
(JNIEnv* env, jclass, jint source)
{
CS_Status status = 0;
@@ -656,12 +707,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: setSourceConnectionStrategy
* Signature: (II)V
*/
JNIEXPORT void JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_setSourceConnectionStrategy
+Java_edu_wpi_first_cscore_CameraServerJNI_setSourceConnectionStrategy
(JNIEnv* env, jclass, jint source, jint strategy)
{
CS_Status status = 0;
@@ -671,12 +722,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: isSourceConnected
* Signature: (I)Z
*/
JNIEXPORT jboolean JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_isSourceConnected
+Java_edu_wpi_first_cscore_CameraServerJNI_isSourceConnected
(JNIEnv* env, jclass, jint source)
{
CS_Status status = 0;
@@ -686,12 +737,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: isSourceEnabled
* Signature: (I)Z
*/
JNIEXPORT jboolean JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_isSourceEnabled
+Java_edu_wpi_first_cscore_CameraServerJNI_isSourceEnabled
(JNIEnv* env, jclass, jint source)
{
CS_Status status = 0;
@@ -701,12 +752,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: getSourceProperty
* Signature: (ILjava/lang/String;)I
*/
JNIEXPORT jint JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_getSourceProperty
+Java_edu_wpi_first_cscore_CameraServerJNI_getSourceProperty
(JNIEnv* env, jclass, jint source, jstring name)
{
if (!name) {
@@ -721,43 +772,47 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: enumerateSourceProperties
* Signature: (I)[I
*/
JNIEXPORT jintArray JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_enumerateSourceProperties
+Java_edu_wpi_first_cscore_CameraServerJNI_enumerateSourceProperties
(JNIEnv* env, jclass, jint source)
{
CS_Status status = 0;
wpi::SmallVector<CS_Property, 32> buf;
auto arr = cs::EnumerateSourceProperties(source, buf, &status);
- if (!CheckStatus(env, status)) return nullptr;
+ if (!CheckStatus(env, status)) {
+ return nullptr;
+ }
return MakeJIntArray(env, arr);
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: getSourceVideoMode
* Signature: (I)Ljava/lang/Object;
*/
JNIEXPORT jobject JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_getSourceVideoMode
+Java_edu_wpi_first_cscore_CameraServerJNI_getSourceVideoMode
(JNIEnv* env, jclass, jint source)
{
CS_Status status = 0;
auto val = cs::GetSourceVideoMode(source, &status);
- if (!CheckStatus(env, status)) return nullptr;
+ if (!CheckStatus(env, status)) {
+ return nullptr;
+ }
return MakeJObject(env, val);
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: setSourceVideoMode
* Signature: (IIIII)Z
*/
JNIEXPORT jboolean JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_setSourceVideoMode
+Java_edu_wpi_first_cscore_CameraServerJNI_setSourceVideoMode
(JNIEnv* env, jclass, jint source, jint pixelFormat, jint width, jint height,
jint fps)
{
@@ -772,12 +827,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: setSourcePixelFormat
* Signature: (II)Z
*/
JNIEXPORT jboolean JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_setSourcePixelFormat
+Java_edu_wpi_first_cscore_CameraServerJNI_setSourcePixelFormat
(JNIEnv* env, jclass, jint source, jint pixelFormat)
{
CS_Status status = 0;
@@ -788,12 +843,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: setSourceResolution
* Signature: (III)Z
*/
JNIEXPORT jboolean JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_setSourceResolution
+Java_edu_wpi_first_cscore_CameraServerJNI_setSourceResolution
(JNIEnv* env, jclass, jint source, jint width, jint height)
{
CS_Status status = 0;
@@ -803,12 +858,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: setSourceFPS
* Signature: (II)Z
*/
JNIEXPORT jboolean JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_setSourceFPS
+Java_edu_wpi_first_cscore_CameraServerJNI_setSourceFPS
(JNIEnv* env, jclass, jint source, jint fps)
{
CS_Status status = 0;
@@ -818,12 +873,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: setSourceConfigJson
* Signature: (ILjava/lang/String;)Z
*/
JNIEXPORT jboolean JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_setSourceConfigJson
+Java_edu_wpi_first_cscore_CameraServerJNI_setSourceConfigJson
(JNIEnv* env, jclass, jint source, jstring config)
{
CS_Status status = 0;
@@ -833,12 +888,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: getSourceConfigJson
* Signature: (I)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_getSourceConfigJson
+Java_edu_wpi_first_cscore_CameraServerJNI_getSourceConfigJson
(JNIEnv* env, jclass, jint source)
{
CS_Status status = 0;
@@ -848,19 +903,23 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: enumerateSourceVideoModes
* Signature: (I)[Ljava/lang/Object;
*/
JNIEXPORT jobjectArray JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_enumerateSourceVideoModes
+Java_edu_wpi_first_cscore_CameraServerJNI_enumerateSourceVideoModes
(JNIEnv* env, jclass, jint source)
{
CS_Status status = 0;
auto arr = cs::EnumerateSourceVideoModes(source, &status);
- if (!CheckStatus(env, status)) return nullptr;
+ if (!CheckStatus(env, status)) {
+ return nullptr;
+ }
jobjectArray jarr = env->NewObjectArray(arr.size(), videoModeCls, nullptr);
- if (!jarr) return nullptr;
+ if (!jarr) {
+ return nullptr;
+ }
for (size_t i = 0; i < arr.size(); ++i) {
JLocal<jobject> jelem{env, MakeJObject(env, arr[i])};
env->SetObjectArrayElement(jarr, i, jelem);
@@ -869,28 +928,30 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: enumerateSourceSinks
* Signature: (I)[I
*/
JNIEXPORT jintArray JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_enumerateSourceSinks
+Java_edu_wpi_first_cscore_CameraServerJNI_enumerateSourceSinks
(JNIEnv* env, jclass, jint source)
{
CS_Status status = 0;
wpi::SmallVector<CS_Sink, 16> buf;
auto arr = cs::EnumerateSourceSinks(source, buf, &status);
- if (!CheckStatus(env, status)) return nullptr;
+ if (!CheckStatus(env, status)) {
+ return nullptr;
+ }
return MakeJIntArray(env, arr);
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: copySource
* Signature: (I)I
*/
JNIEXPORT jint JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_copySource
+Java_edu_wpi_first_cscore_CameraServerJNI_copySource
(JNIEnv* env, jclass, jint source)
{
CS_Status status = 0;
@@ -900,12 +961,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: releaseSource
* Signature: (I)V
*/
JNIEXPORT void JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_releaseSource
+Java_edu_wpi_first_cscore_CameraServerJNI_releaseSource
(JNIEnv* env, jclass, jint source)
{
CS_Status status = 0;
@@ -914,12 +975,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: setCameraBrightness
* Signature: (II)V
*/
JNIEXPORT void JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_setCameraBrightness
+Java_edu_wpi_first_cscore_CameraServerJNI_setCameraBrightness
(JNIEnv* env, jclass, jint source, jint brightness)
{
CS_Status status = 0;
@@ -928,12 +989,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: getCameraBrightness
* Signature: (I)I
*/
JNIEXPORT jint JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_getCameraBrightness
+Java_edu_wpi_first_cscore_CameraServerJNI_getCameraBrightness
(JNIEnv* env, jclass, jint source)
{
CS_Status status = 0;
@@ -943,12 +1004,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: setCameraWhiteBalanceAuto
* Signature: (I)V
*/
JNIEXPORT void JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_setCameraWhiteBalanceAuto
+Java_edu_wpi_first_cscore_CameraServerJNI_setCameraWhiteBalanceAuto
(JNIEnv* env, jclass, jint source)
{
CS_Status status = 0;
@@ -957,12 +1018,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: setCameraWhiteBalanceHoldCurrent
* Signature: (I)V
*/
JNIEXPORT void JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_setCameraWhiteBalanceHoldCurrent
+Java_edu_wpi_first_cscore_CameraServerJNI_setCameraWhiteBalanceHoldCurrent
(JNIEnv* env, jclass, jint source)
{
CS_Status status = 0;
@@ -971,12 +1032,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: setCameraWhiteBalanceManual
* Signature: (II)V
*/
JNIEXPORT void JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_setCameraWhiteBalanceManual
+Java_edu_wpi_first_cscore_CameraServerJNI_setCameraWhiteBalanceManual
(JNIEnv* env, jclass, jint source, jint value)
{
CS_Status status = 0;
@@ -985,12 +1046,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: setCameraExposureAuto
* Signature: (I)V
*/
JNIEXPORT void JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_setCameraExposureAuto
+Java_edu_wpi_first_cscore_CameraServerJNI_setCameraExposureAuto
(JNIEnv* env, jclass, jint source)
{
CS_Status status = 0;
@@ -999,12 +1060,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: setCameraExposureHoldCurrent
* Signature: (I)V
*/
JNIEXPORT void JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_setCameraExposureHoldCurrent
+Java_edu_wpi_first_cscore_CameraServerJNI_setCameraExposureHoldCurrent
(JNIEnv* env, jclass, jint source)
{
CS_Status status = 0;
@@ -1013,12 +1074,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: setCameraExposureManual
* Signature: (II)V
*/
JNIEXPORT void JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_setCameraExposureManual
+Java_edu_wpi_first_cscore_CameraServerJNI_setCameraExposureManual
(JNIEnv* env, jclass, jint source, jint value)
{
CS_Status status = 0;
@@ -1027,12 +1088,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: setUsbCameraPath
* Signature: (ILjava/lang/String;)V
*/
JNIEXPORT void JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_setUsbCameraPath
+Java_edu_wpi_first_cscore_CameraServerJNI_setUsbCameraPath
(JNIEnv* env, jclass, jint source, jstring path)
{
CS_Status status = 0;
@@ -1041,57 +1102,63 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: getUsbCameraPath
* Signature: (I)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_getUsbCameraPath
+Java_edu_wpi_first_cscore_CameraServerJNI_getUsbCameraPath
(JNIEnv* env, jclass, jint source)
{
CS_Status status = 0;
auto str = cs::GetUsbCameraPath(source, &status);
- if (!CheckStatus(env, status)) return nullptr;
+ if (!CheckStatus(env, status)) {
+ return nullptr;
+ }
return MakeJString(env, str);
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: getUsbCameraInfo
* Signature: (I)Ljava/lang/Object;
*/
JNIEXPORT jobject JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_getUsbCameraInfo
+Java_edu_wpi_first_cscore_CameraServerJNI_getUsbCameraInfo
(JNIEnv* env, jclass, jint source)
{
CS_Status status = 0;
auto info = cs::GetUsbCameraInfo(source, &status);
- if (!CheckStatus(env, status)) return nullptr;
+ if (!CheckStatus(env, status)) {
+ return nullptr;
+ }
return MakeJObject(env, info);
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: getHttpCameraKind
* Signature: (I)I
*/
JNIEXPORT jint JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_getHttpCameraKind
+Java_edu_wpi_first_cscore_CameraServerJNI_getHttpCameraKind
(JNIEnv* env, jclass, jint source)
{
CS_Status status = 0;
auto kind = cs::GetHttpCameraKind(source, &status);
- if (!CheckStatus(env, status)) return 0;
+ if (!CheckStatus(env, status)) {
+ return 0;
+ }
return kind;
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: setHttpCameraUrls
* Signature: (I[Ljava/lang/Object;)V
*/
JNIEXPORT void JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_setHttpCameraUrls
+Java_edu_wpi_first_cscore_CameraServerJNI_setHttpCameraUrls
(JNIEnv* env, jclass, jint source, jobjectArray urls)
{
if (!urls) {
@@ -1108,7 +1175,7 @@
// TODO
return;
}
- vec.push_back(JStringRef{env, elem}.str());
+ vec.emplace_back(JStringRef{env, elem}.str());
}
CS_Status status = 0;
cs::SetHttpCameraUrls(source, vec, &status);
@@ -1116,27 +1183,29 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: getHttpCameraUrls
* Signature: (I)[Ljava/lang/Object;
*/
JNIEXPORT jobjectArray JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_getHttpCameraUrls
+Java_edu_wpi_first_cscore_CameraServerJNI_getHttpCameraUrls
(JNIEnv* env, jclass, jint source)
{
CS_Status status = 0;
auto arr = cs::GetHttpCameraUrls(source, &status);
- if (!CheckStatus(env, status)) return nullptr;
+ if (!CheckStatus(env, status)) {
+ return nullptr;
+ }
return MakeJStringArray(env, arr);
}
/*
- * Class: edu_wpi_cscore_CameraServerCvJNI
+ * Class: edu_wpi_first_cscore_CameraServerCvJNI
* Method: putSourceFrame
* Signature: (IJ)V
*/
JNIEXPORT void JNICALL
-Java_edu_wpi_cscore_CameraServerCvJNI_putSourceFrame
+Java_edu_wpi_first_cscore_CameraServerCvJNI_putSourceFrame
(JNIEnv* env, jclass, jint source, jlong imageNativeObj)
{
try {
@@ -1147,19 +1216,19 @@
} catch (const std::exception& e) {
ThrowJavaException(env, &e);
} catch (...) {
- ThrowJavaException(env, 0);
+ ThrowJavaException(env, nullptr);
}
}
// int width, int height, int pixelFormat, int totalData
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: putRawSourceFrameBB
* Signature: (ILjava/lang/Object;IIII)V
*/
JNIEXPORT void JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_putRawSourceFrameBB
+Java_edu_wpi_first_cscore_CameraServerJNI_putRawSourceFrameBB
(JNIEnv* env, jclass, jint source, jobject byteBuffer, jint width,
jint height, jint pixelFormat, jint totalData)
{
@@ -1176,12 +1245,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: putRawSourceFrame
* Signature: (IJIIII)V
*/
JNIEXPORT void JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_putRawSourceFrame
+Java_edu_wpi_first_cscore_CameraServerJNI_putRawSourceFrame
(JNIEnv* env, jclass, jint source, jlong ptr, jint width, jint height,
jint pixelFormat, jint totalData)
{
@@ -1197,12 +1266,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: notifySourceError
* Signature: (ILjava/lang/String;)V
*/
JNIEXPORT void JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_notifySourceError
+Java_edu_wpi_first_cscore_CameraServerJNI_notifySourceError
(JNIEnv* env, jclass, jint source, jstring msg)
{
if (!msg) {
@@ -1215,12 +1284,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: setSourceConnected
* Signature: (IZ)V
*/
JNIEXPORT void JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_setSourceConnected
+Java_edu_wpi_first_cscore_CameraServerJNI_setSourceConnected
(JNIEnv* env, jclass, jint source, jboolean connected)
{
CS_Status status = 0;
@@ -1229,12 +1298,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: setSourceDescription
* Signature: (ILjava/lang/String;)V
*/
JNIEXPORT void JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_setSourceDescription
+Java_edu_wpi_first_cscore_CameraServerJNI_setSourceDescription
(JNIEnv* env, jclass, jint source, jstring description)
{
if (!description) {
@@ -1247,12 +1316,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: createSourceProperty
* Signature: (ILjava/lang/String;IIIIII)I
*/
JNIEXPORT jint JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_createSourceProperty
+Java_edu_wpi_first_cscore_CameraServerJNI_createSourceProperty
(JNIEnv* env, jclass, jint source, jstring name, jint kind, jint minimum,
jint maximum, jint step, jint defaultValue, jint value)
{
@@ -1265,12 +1334,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: setSourceEnumPropertyChoices
* Signature: (II[Ljava/lang/Object;)V
*/
JNIEXPORT void JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_setSourceEnumPropertyChoices
+Java_edu_wpi_first_cscore_CameraServerJNI_setSourceEnumPropertyChoices
(JNIEnv* env, jclass, jint source, jint property, jobjectArray choices)
{
if (!choices) {
@@ -1287,7 +1356,7 @@
// TODO
return;
}
- vec.push_back(JStringRef{env, elem}.str());
+ vec.emplace_back(JStringRef{env, elem}.str());
}
CS_Status status = 0;
cs::SetSourceEnumPropertyChoices(source, property, vec, &status);
@@ -1295,12 +1364,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: createMjpegServer
* Signature: (Ljava/lang/String;Ljava/lang/String;I)I
*/
JNIEXPORT jint JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_createMjpegServer
+Java_edu_wpi_first_cscore_CameraServerJNI_createMjpegServer
(JNIEnv* env, jclass, jstring name, jstring listenAddress, jint port)
{
if (!name) {
@@ -1320,12 +1389,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerCvJNI
+ * Class: edu_wpi_first_cscore_CameraServerCvJNI
* Method: createCvSink
* Signature: (Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL
-Java_edu_wpi_cscore_CameraServerCvJNI_createCvSink
+Java_edu_wpi_first_cscore_CameraServerCvJNI_createCvSink
(JNIEnv* env, jclass, jstring name)
{
if (!name) {
@@ -1339,12 +1408,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: createRawSink
* Signature: (Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_createRawSink
+Java_edu_wpi_first_cscore_CameraServerJNI_createRawSink
(JNIEnv* env, jclass, jstring name)
{
if (!name) {
@@ -1358,12 +1427,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: getSinkKind
* Signature: (I)I
*/
JNIEXPORT jint JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_getSinkKind
+Java_edu_wpi_first_cscore_CameraServerJNI_getSinkKind
(JNIEnv* env, jclass, jint sink)
{
CS_Status status = 0;
@@ -1373,44 +1442,48 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: getSinkName
* Signature: (I)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_getSinkName
+Java_edu_wpi_first_cscore_CameraServerJNI_getSinkName
(JNIEnv* env, jclass, jint sink)
{
CS_Status status = 0;
wpi::SmallString<128> buf;
auto str = cs::GetSinkName(sink, buf, &status);
- if (!CheckStatus(env, status)) return nullptr;
+ if (!CheckStatus(env, status)) {
+ return nullptr;
+ }
return MakeJString(env, str);
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: getSinkDescription
* Signature: (I)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_getSinkDescription
+Java_edu_wpi_first_cscore_CameraServerJNI_getSinkDescription
(JNIEnv* env, jclass, jint sink)
{
CS_Status status = 0;
wpi::SmallString<128> buf;
auto str = cs::GetSinkDescription(sink, buf, &status);
- if (!CheckStatus(env, status)) return nullptr;
+ if (!CheckStatus(env, status)) {
+ return nullptr;
+ }
return MakeJString(env, str);
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: getSinkProperty
* Signature: (ILjava/lang/String;)I
*/
JNIEXPORT jint JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_getSinkProperty
+Java_edu_wpi_first_cscore_CameraServerJNI_getSinkProperty
(JNIEnv* env, jclass, jint sink, jstring name)
{
if (!name) {
@@ -1424,28 +1497,30 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: enumerateSinkProperties
* Signature: (I)[I
*/
JNIEXPORT jintArray JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_enumerateSinkProperties
+Java_edu_wpi_first_cscore_CameraServerJNI_enumerateSinkProperties
(JNIEnv* env, jclass, jint source)
{
CS_Status status = 0;
wpi::SmallVector<CS_Property, 32> buf;
auto arr = cs::EnumerateSinkProperties(source, buf, &status);
- if (!CheckStatus(env, status)) return nullptr;
+ if (!CheckStatus(env, status)) {
+ return nullptr;
+ }
return MakeJIntArray(env, arr);
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: setSinkConfigJson
* Signature: (ILjava/lang/String;)Z
*/
JNIEXPORT jboolean JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_setSinkConfigJson
+Java_edu_wpi_first_cscore_CameraServerJNI_setSinkConfigJson
(JNIEnv* env, jclass, jint source, jstring config)
{
CS_Status status = 0;
@@ -1455,12 +1530,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: getSinkConfigJson
* Signature: (I)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_getSinkConfigJson
+Java_edu_wpi_first_cscore_CameraServerJNI_getSinkConfigJson
(JNIEnv* env, jclass, jint source)
{
CS_Status status = 0;
@@ -1470,12 +1545,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: setSinkSource
* Signature: (II)V
*/
JNIEXPORT void JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_setSinkSource
+Java_edu_wpi_first_cscore_CameraServerJNI_setSinkSource
(JNIEnv* env, jclass, jint sink, jint source)
{
CS_Status status = 0;
@@ -1484,12 +1559,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: getSinkSourceProperty
* Signature: (ILjava/lang/String;)I
*/
JNIEXPORT jint JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_getSinkSourceProperty
+Java_edu_wpi_first_cscore_CameraServerJNI_getSinkSourceProperty
(JNIEnv* env, jclass, jint sink, jstring name)
{
if (!name) {
@@ -1504,12 +1579,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: getSinkSource
* Signature: (I)I
*/
JNIEXPORT jint JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_getSinkSource
+Java_edu_wpi_first_cscore_CameraServerJNI_getSinkSource
(JNIEnv* env, jclass, jint sink)
{
CS_Status status = 0;
@@ -1519,12 +1594,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: copySink
* Signature: (I)I
*/
JNIEXPORT jint JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_copySink
+Java_edu_wpi_first_cscore_CameraServerJNI_copySink
(JNIEnv* env, jclass, jint sink)
{
CS_Status status = 0;
@@ -1534,12 +1609,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: releaseSink
* Signature: (I)V
*/
JNIEXPORT void JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_releaseSink
+Java_edu_wpi_first_cscore_CameraServerJNI_releaseSink
(JNIEnv* env, jclass, jint sink)
{
CS_Status status = 0;
@@ -1548,27 +1623,29 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: getMjpegServerListenAddress
* Signature: (I)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_getMjpegServerListenAddress
+Java_edu_wpi_first_cscore_CameraServerJNI_getMjpegServerListenAddress
(JNIEnv* env, jclass, jint sink)
{
CS_Status status = 0;
auto str = cs::GetMjpegServerListenAddress(sink, &status);
- if (!CheckStatus(env, status)) return nullptr;
+ if (!CheckStatus(env, status)) {
+ return nullptr;
+ }
return MakeJString(env, str);
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: getMjpegServerPort
* Signature: (I)I
*/
JNIEXPORT jint JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_getMjpegServerPort
+Java_edu_wpi_first_cscore_CameraServerJNI_getMjpegServerPort
(JNIEnv* env, jclass, jint sink)
{
CS_Status status = 0;
@@ -1578,12 +1655,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: setSinkDescription
* Signature: (ILjava/lang/String;)V
*/
JNIEXPORT void JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_setSinkDescription
+Java_edu_wpi_first_cscore_CameraServerJNI_setSinkDescription
(JNIEnv* env, jclass, jint sink, jstring description)
{
if (!description) {
@@ -1596,12 +1673,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerCvJNI
+ * Class: edu_wpi_first_cscore_CameraServerCvJNI
* Method: grabSinkFrame
* Signature: (IJ)J
*/
JNIEXPORT jlong JNICALL
-Java_edu_wpi_cscore_CameraServerCvJNI_grabSinkFrame
+Java_edu_wpi_first_cscore_CameraServerCvJNI_grabSinkFrame
(JNIEnv* env, jclass, jint sink, jlong imageNativeObj)
{
try {
@@ -1614,18 +1691,18 @@
ThrowJavaException(env, &e);
return 0;
} catch (...) {
- ThrowJavaException(env, 0);
+ ThrowJavaException(env, nullptr);
return 0;
}
}
/*
- * Class: edu_wpi_cscore_CameraServerCvJNI
+ * Class: edu_wpi_first_cscore_CameraServerCvJNI
* Method: grabSinkFrameTimeout
* Signature: (IJD)J
*/
JNIEXPORT jlong JNICALL
-Java_edu_wpi_cscore_CameraServerCvJNI_grabSinkFrameTimeout
+Java_edu_wpi_first_cscore_CameraServerCvJNI_grabSinkFrameTimeout
(JNIEnv* env, jclass, jint sink, jlong imageNativeObj, jdouble timeout)
{
try {
@@ -1638,7 +1715,7 @@
ThrowJavaException(env, &e);
return 0;
} catch (...) {
- ThrowJavaException(env, 0);
+ ThrowJavaException(env, nullptr);
return 0;
}
}
@@ -1661,12 +1738,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: grabRawSinkFrameImpl
* Signature: (ILjava/lang/Object;JLjava/lang/Object;III)J
*/
JNIEXPORT jlong JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_grabRawSinkFrameImpl
+Java_edu_wpi_first_cscore_CameraServerJNI_grabRawSinkFrameImpl
(JNIEnv* env, jclass, jint sink, jobject rawFrameObj, jlong rawFramePtr,
jobject byteBuffer, jint width, jint height, jint pixelFormat)
{
@@ -1686,12 +1763,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: grabRawSinkFrameTimeoutImpl
* Signature: (ILjava/lang/Object;JLjava/lang/Object;IIID)J
*/
JNIEXPORT jlong JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_grabRawSinkFrameTimeoutImpl
+Java_edu_wpi_first_cscore_CameraServerJNI_grabRawSinkFrameTimeoutImpl
(JNIEnv* env, jclass, jint sink, jobject rawFrameObj, jlong rawFramePtr,
jobject byteBuffer, jint width, jint height, jint pixelFormat,
jdouble timeout)
@@ -1713,28 +1790,30 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: getSinkError
* Signature: (I)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_getSinkError
+Java_edu_wpi_first_cscore_CameraServerJNI_getSinkError
(JNIEnv* env, jclass, jint sink)
{
CS_Status status = 0;
wpi::SmallString<128> buf;
auto str = cs::GetSinkError(sink, buf, &status);
- if (!CheckStatus(env, status)) return nullptr;
+ if (!CheckStatus(env, status)) {
+ return nullptr;
+ }
return MakeJString(env, str);
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: setSinkEnabled
* Signature: (IZ)V
*/
JNIEXPORT void JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_setSinkEnabled
+Java_edu_wpi_first_cscore_CameraServerJNI_setSinkEnabled
(JNIEnv* env, jclass, jint sink, jboolean enabled)
{
CS_Status status = 0;
@@ -1743,12 +1822,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: addListener
* Signature: (Ljava/lang/Object;IZ)I
*/
JNIEXPORT jint JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_addListener
+Java_edu_wpi_first_cscore_CameraServerJNI_addListener
(JNIEnv* envouter, jclass, jobject listener, jint eventMask,
jboolean immediateNotify)
{
@@ -1763,17 +1842,23 @@
// cls is a temporary here; cannot be used within callback functor
jclass cls = envouter->GetObjectClass(listener);
- if (!cls) return 0;
+ if (!cls) {
+ return 0;
+ }
// method ids, on the other hand, are safe to retain
jmethodID mid = envouter->GetMethodID(cls, "accept", "(Ljava/lang/Object;)V");
- if (!mid) return 0;
+ if (!mid) {
+ return 0;
+ }
CS_Status status = 0;
CS_Listener handle = cs::AddListener(
[=](const cs::RawEvent& event) {
JNIEnv* env = listenerEnv;
- if (!env || !env->functions) return;
+ if (!env || !env->functions) {
+ return;
+ }
// get the handler
auto handler = listener_global->obj();
@@ -1785,7 +1870,9 @@
env->ExceptionClear();
return;
}
- if (!jobj) return;
+ if (!jobj) {
+ return;
+ }
env->CallVoidMethod(handler, mid, jobj.obj());
if (env->ExceptionCheck()) {
@@ -1799,12 +1886,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: removeListener
* Signature: (I)V
*/
JNIEXPORT void JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_removeListener
+Java_edu_wpi_first_cscore_CameraServerJNI_removeListener
(JNIEnv* env, jclass, jint handle)
{
CS_Status status = 0;
@@ -1813,36 +1900,122 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
+ * Method: createListenerPoller
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL
+Java_edu_wpi_first_cscore_CameraServerJNI_createListenerPoller
+ (JNIEnv*, jclass)
+{
+ return cs::CreateListenerPoller();
+}
+
+/*
+ * Class: edu_wpi_first_cscore_CameraServerJNI
+ * Method: destroyListenerPoller
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL
+Java_edu_wpi_first_cscore_CameraServerJNI_destroyListenerPoller
+ (JNIEnv*, jclass, jint poller)
+{
+ cs::DestroyListenerPoller(poller);
+}
+
+/*
+ * Class: edu_wpi_first_cscore_CameraServerJNI
+ * Method: addPolledListener
+ * Signature: (IIZ)I
+ */
+JNIEXPORT jint JNICALL
+Java_edu_wpi_first_cscore_CameraServerJNI_addPolledListener
+ (JNIEnv* env, jclass, jint poller, jint eventMask, jboolean immediateNotify)
+{
+ CS_Status status = 0;
+ auto rv = cs::AddPolledListener(poller, eventMask, immediateNotify, &status);
+ CheckStatus(env, status);
+ return rv;
+}
+
+/*
+ * Class: edu_wpi_first_cscore_CameraServerJNI
+ * Method: pollListener
+ * Signature: (I)[Ljava/lang/Object;
+ */
+JNIEXPORT jobjectArray JNICALL
+Java_edu_wpi_first_cscore_CameraServerJNI_pollListener
+ (JNIEnv* env, jclass, jint poller)
+{
+ auto events = cs::PollListener(poller);
+ if (events.empty()) {
+ interruptedEx.Throw(env, "PollListener interrupted");
+ return nullptr;
+ }
+ return MakeJObject(env, events);
+}
+
+/*
+ * Class: edu_wpi_first_cscore_CameraServerJNI
+ * Method: pollListenerTimeout
+ * Signature: (ID)[Ljava/lang/Object;
+ */
+JNIEXPORT jobjectArray JNICALL
+Java_edu_wpi_first_cscore_CameraServerJNI_pollListenerTimeout
+ (JNIEnv* env, jclass, jint poller, jdouble timeout)
+{
+ bool timed_out = false;
+ auto events = cs::PollListener(poller, timeout, &timed_out);
+ if (events.empty() && !timed_out) {
+ interruptedEx.Throw(env, "PollListener interrupted");
+ return nullptr;
+ }
+ return MakeJObject(env, events);
+}
+
+/*
+ * Class: edu_wpi_first_cscore_CameraServerJNI
+ * Method: cancelPollListener
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL
+Java_edu_wpi_first_cscore_CameraServerJNI_cancelPollListener
+ (JNIEnv*, jclass, jint poller)
+{
+ cs::CancelPollListener(poller);
+}
+
+/*
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: setTelemetryPeriod
* Signature: (D)V
*/
JNIEXPORT void JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_setTelemetryPeriod
+Java_edu_wpi_first_cscore_CameraServerJNI_setTelemetryPeriod
(JNIEnv* env, jclass, jdouble seconds)
{
cs::SetTelemetryPeriod(seconds);
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: getTelemetryElapsedTime
* Signature: ()D
*/
JNIEXPORT jdouble JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_getTelemetryElapsedTime
+Java_edu_wpi_first_cscore_CameraServerJNI_getTelemetryElapsedTime
(JNIEnv* env, jclass)
{
return cs::GetTelemetryElapsedTime();
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: getTelemetryValue
* Signature: (II)J
*/
JNIEXPORT jlong JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_getTelemetryValue
+Java_edu_wpi_first_cscore_CameraServerJNI_getTelemetryValue
(JNIEnv* env, jclass, jint handle, jint kind)
{
CS_Status status = 0;
@@ -1853,12 +2026,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: getTelemetryAverageValue
* Signature: (II)D
*/
JNIEXPORT jdouble JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_getTelemetryAverageValue
+Java_edu_wpi_first_cscore_CameraServerJNI_getTelemetryAverageValue
(JNIEnv* env, jclass, jint handle, jint kind)
{
CS_Status status = 0;
@@ -1869,20 +2042,24 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: enumerateUsbCameras
* Signature: ()[Ljava/lang/Object;
*/
JNIEXPORT jobjectArray JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_enumerateUsbCameras
+Java_edu_wpi_first_cscore_CameraServerJNI_enumerateUsbCameras
(JNIEnv* env, jclass)
{
CS_Status status = 0;
auto arr = cs::EnumerateUsbCameras(&status);
- if (!CheckStatus(env, status)) return nullptr;
+ if (!CheckStatus(env, status)) {
+ return nullptr;
+ }
jobjectArray jarr =
env->NewObjectArray(arr.size(), usbCameraInfoCls, nullptr);
- if (!jarr) return nullptr;
+ if (!jarr) {
+ return nullptr;
+ }
for (size_t i = 0; i < arr.size(); ++i) {
JLocal<jobject> jelem{env, MakeJObject(env, arr[i])};
env->SetObjectArrayElement(jarr, i, jelem);
@@ -1891,56 +2068,60 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: enumerateSources
* Signature: ()[I
*/
JNIEXPORT jintArray JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_enumerateSources
+Java_edu_wpi_first_cscore_CameraServerJNI_enumerateSources
(JNIEnv* env, jclass)
{
CS_Status status = 0;
wpi::SmallVector<CS_Source, 16> buf;
auto arr = cs::EnumerateSourceHandles(buf, &status);
- if (!CheckStatus(env, status)) return nullptr;
+ if (!CheckStatus(env, status)) {
+ return nullptr;
+ }
return MakeJIntArray(env, arr);
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: enumerateSinks
* Signature: ()[I
*/
JNIEXPORT jintArray JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_enumerateSinks
+Java_edu_wpi_first_cscore_CameraServerJNI_enumerateSinks
(JNIEnv* env, jclass)
{
CS_Status status = 0;
wpi::SmallVector<CS_Sink, 16> buf;
auto arr = cs::EnumerateSinkHandles(buf, &status);
- if (!CheckStatus(env, status)) return nullptr;
+ if (!CheckStatus(env, status)) {
+ return nullptr;
+ }
return MakeJIntArray(env, arr);
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: getHostname
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_getHostname
+Java_edu_wpi_first_cscore_CameraServerJNI_getHostname
(JNIEnv* env, jclass)
{
return MakeJString(env, cs::GetHostname());
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: getNetworkInterfaces
* Signature: ()[Ljava/lang/Object;
*/
JNIEXPORT jobjectArray JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_getNetworkInterfaces
+Java_edu_wpi_first_cscore_CameraServerJNI_getNetworkInterfaces
(JNIEnv* env, jclass)
{
return MakeJStringArray(env, cs::GetNetworkInterfaces());
@@ -1959,8 +2140,8 @@
void CallJava(JNIEnv* env, jobject func, jmethodID mid) {
JLocal<jstring> file{env, MakeJString(env, m_file)};
JLocal<jstring> msg{env, MakeJString(env, m_msg)};
- env->CallVoidMethod(func, mid, (jint)m_level, file.obj(), (jint)m_line,
- msg.obj());
+ env->CallVoidMethod(func, mid, static_cast<jint>(m_level), file.obj(),
+ static_cast<jint>(m_line), msg.obj());
}
static const char* GetName() { return "CSLogger"; }
@@ -1973,19 +2154,19 @@
std::string m_msg;
};
-typedef JSingletonCallbackManager<LogMessage> LoggerJNI;
+using LoggerJNI = JSingletonCallbackManager<LogMessage>;
} // namespace
extern "C" {
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: setLogger
* Signature: (Ljava/lang/Object;I)V
*/
JNIEXPORT void JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_setLogger
+Java_edu_wpi_first_cscore_CameraServerJNI_setLogger
(JNIEnv* env, jclass, jobject func, jint minLevel)
{
if (!func) {
@@ -1994,12 +2175,16 @@
}
// cls is a temporary here; cannot be used within callback functor
jclass cls = env->GetObjectClass(func);
- if (!cls) return;
+ if (!cls) {
+ return;
+ }
// method ids, on the other hand, are safe to retain
jmethodID mid = env->GetMethodID(cls, "apply",
"(ILjava/lang/String;ILjava/lang/String;)V");
- if (!mid) return;
+ if (!mid) {
+ return;
+ }
auto& logger = LoggerJNI::GetInstance();
logger.Start();
@@ -2014,12 +2199,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: allocateRawFrame
* Signature: ()J
*/
JNIEXPORT jlong JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_allocateRawFrame
+Java_edu_wpi_first_cscore_CameraServerJNI_allocateRawFrame
(JNIEnv*, jclass)
{
cs::RawFrame* rawFrame = new cs::RawFrame{};
@@ -2028,12 +2213,12 @@
}
/*
- * Class: edu_wpi_cscore_CameraServerJNI
+ * Class: edu_wpi_first_cscore_CameraServerJNI
* Method: freeRawFrame
* Signature: (J)V
*/
JNIEXPORT void JNICALL
-Java_edu_wpi_cscore_CameraServerJNI_freeRawFrame
+Java_edu_wpi_first_cscore_CameraServerJNI_freeRawFrame
(JNIEnv*, jclass, jlong rawFrame)
{
cs::RawFrame* ptr =
diff --git a/cscore/src/main/native/include/cscore.h b/cscore/src/main/native/include/cscore.h
index eff3856..085d6c7 100644
--- a/cscore/src/main/native/include/cscore.h
+++ b/cscore/src/main/native/include/cscore.h
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2018 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#ifndef CSCORE_CSCORE_H_
#define CSCORE_CSCORE_H_
diff --git a/cscore/src/main/native/include/cscore_c.h b/cscore/src/main/native/include/cscore_c.h
index ee5d33a..76bd836 100644
--- a/cscore/src/main/native/include/cscore_c.h
+++ b/cscore/src/main/native/include/cscore_c.h
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2020 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#ifndef CSCORE_CSCORE_C_H_
#define CSCORE_CSCORE_C_H_
@@ -49,6 +46,7 @@
typedef int CS_Handle;
typedef CS_Handle CS_Property;
typedef CS_Handle CS_Listener;
+typedef CS_Handle CS_ListenerPoller;
typedef CS_Handle CS_Sink;
typedef CS_Handle CS_Source;
/** @} */
@@ -172,7 +170,8 @@
CS_TELEMETRY_UPDATED = 0x8000,
CS_SINK_PROPERTY_CREATED = 0x10000,
CS_SINK_PROPERTY_VALUE_UPDATED = 0x20000,
- CS_SINK_PROPERTY_CHOICES_UPDATED = 0x40000
+ CS_SINK_PROPERTY_CHOICES_UPDATED = 0x40000,
+ CS_USB_CAMERAS_CHANGED = 0x80000
};
/**
@@ -225,6 +224,9 @@
enum CS_PropertyKind propertyKind;
int value;
const char* valueStr;
+
+ // Listener that was triggered
+ CS_Listener listener;
};
/**
@@ -432,9 +434,19 @@
void CS_SetListenerOnExit(void (*onExit)(void* data), void* data);
CS_Listener CS_AddListener(
void* data, void (*callback)(void* data, const struct CS_Event* event),
- int eventMask, int immediateNotify, CS_Status* status);
+ int eventMask, CS_Bool immediateNotify, CS_Status* status);
void CS_RemoveListener(CS_Listener handle, CS_Status* status);
+
+CS_ListenerPoller CS_CreateListenerPoller(void);
+void CS_DestroyListenerPoller(CS_ListenerPoller poller);
+CS_Listener CS_AddPolledListener(CS_ListenerPoller poller, int eventMask,
+ CS_Bool immediateNotify, CS_Status* status);
+struct CS_Event* CS_PollListener(CS_ListenerPoller poller, int* count);
+struct CS_Event* CS_PollListenerTimeout(CS_ListenerPoller poller, int* count,
+ double timeout, CS_Bool* timedOut);
+void CS_FreeEvents(struct CS_Event* arr, int count);
+void CS_CancelPollListener(CS_ListenerPoller poller);
/** @} */
int CS_NotifierDestroyed(void);
diff --git a/cscore/src/main/native/include/cscore_cpp.h b/cscore/src/main/native/include/cscore_cpp.h
index 1ee1615..8b1eab1 100644
--- a/cscore/src/main/native/include/cscore_cpp.h
+++ b/cscore/src/main/native/include/cscore_cpp.h
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2015-2020 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#ifndef CSCORE_CSCORE_CPP_H_
#define CSCORE_CSCORE_CPP_H_
@@ -12,12 +9,11 @@
#include <functional>
#include <string>
+#include <string_view>
#include <vector>
-#include <wpi/ArrayRef.h>
#include <wpi/SmallVector.h>
-#include <wpi/StringRef.h>
-#include <wpi/Twine.h>
+#include <wpi/span.h>
#include "cscore_c.h"
@@ -119,34 +115,36 @@
kTelemetryUpdated = CS_TELEMETRY_UPDATED,
kSinkPropertyCreated = CS_SINK_PROPERTY_CREATED,
kSinkPropertyValueUpdated = CS_SINK_PROPERTY_VALUE_UPDATED,
- kSinkPropertyChoicesUpdated = CS_SINK_PROPERTY_CHOICES_UPDATED
+ kSinkPropertyChoicesUpdated = CS_SINK_PROPERTY_CHOICES_UPDATED,
+ kUsbCamerasChanged = CS_USB_CAMERAS_CHANGED
};
RawEvent() = default;
explicit RawEvent(RawEvent::Kind kind_) : kind{kind_} {}
- RawEvent(const wpi::Twine& name_, CS_Handle handle_, RawEvent::Kind kind_)
- : kind{kind_}, name{name_.str()} {
+ RawEvent(std::string_view name_, CS_Handle handle_, RawEvent::Kind kind_)
+ : kind{kind_}, name{name_} {
if (kind_ == kSinkCreated || kind_ == kSinkDestroyed ||
- kind_ == kSinkEnabled || kind_ == kSinkDisabled)
+ kind_ == kSinkEnabled || kind_ == kSinkDisabled) {
sinkHandle = handle_;
- else
+ } else {
sourceHandle = handle_;
+ }
}
- RawEvent(const wpi::Twine& name_, CS_Source source_, const VideoMode& mode_)
+ RawEvent(std::string_view name_, CS_Source source_, const VideoMode& mode_)
: kind{kSourceVideoModeChanged},
sourceHandle{source_},
- name{name_.str()},
+ name{name_},
mode{mode_} {}
- RawEvent(const wpi::Twine& name_, CS_Source source_, RawEvent::Kind kind_,
+ RawEvent(std::string_view name_, CS_Source source_, RawEvent::Kind kind_,
CS_Property property_, CS_PropertyKind propertyKind_, int value_,
- const wpi::Twine& valueStr_)
+ std::string_view valueStr_)
: kind{kind_},
sourceHandle{source_},
- name{name_.str()},
+ name{name_},
propertyHandle{property_},
propertyKind{propertyKind_},
value{value_},
- valueStr{valueStr_.str()} {}
+ valueStr{valueStr_} {}
Kind kind;
@@ -165,6 +163,9 @@
CS_PropertyKind propertyKind;
int value;
std::string valueStr;
+
+ // Listener that was triggered
+ CS_Listener listener{0};
};
/**
@@ -173,9 +174,9 @@
*/
CS_PropertyKind GetPropertyKind(CS_Property property, CS_Status* status);
std::string GetPropertyName(CS_Property property, CS_Status* status);
-wpi::StringRef GetPropertyName(CS_Property property,
- wpi::SmallVectorImpl<char>& buf,
- CS_Status* status);
+std::string_view GetPropertyName(CS_Property property,
+ wpi::SmallVectorImpl<char>& buf,
+ CS_Status* status);
int GetProperty(CS_Property property, CS_Status* status);
void SetProperty(CS_Property property, int value, CS_Status* status);
int GetPropertyMin(CS_Property property, CS_Status* status);
@@ -183,10 +184,10 @@
int GetPropertyStep(CS_Property property, CS_Status* status);
int GetPropertyDefault(CS_Property property, CS_Status* status);
std::string GetStringProperty(CS_Property property, CS_Status* status);
-wpi::StringRef GetStringProperty(CS_Property property,
- wpi::SmallVectorImpl<char>& buf,
- CS_Status* status);
-void SetStringProperty(CS_Property property, const wpi::Twine& value,
+std::string_view GetStringProperty(CS_Property property,
+ wpi::SmallVectorImpl<char>& buf,
+ CS_Status* status);
+void SetStringProperty(CS_Property property, std::string_view value,
CS_Status* status);
std::vector<std::string> GetEnumPropertyChoices(CS_Property property,
CS_Status* status);
@@ -196,16 +197,15 @@
* @defgroup cscore_source_create_func Source Creation Functions
* @{
*/
-CS_Source CreateUsbCameraDev(const wpi::Twine& name, int dev,
- CS_Status* status);
-CS_Source CreateUsbCameraPath(const wpi::Twine& name, const wpi::Twine& path,
+CS_Source CreateUsbCameraDev(std::string_view name, int dev, CS_Status* status);
+CS_Source CreateUsbCameraPath(std::string_view name, std::string_view path,
CS_Status* status);
-CS_Source CreateHttpCamera(const wpi::Twine& name, const wpi::Twine& url,
+CS_Source CreateHttpCamera(std::string_view name, std::string_view url,
CS_HttpCameraKind kind, CS_Status* status);
-CS_Source CreateHttpCamera(const wpi::Twine& name,
- wpi::ArrayRef<std::string> urls,
+CS_Source CreateHttpCamera(std::string_view name,
+ wpi::span<const std::string> urls,
CS_HttpCameraKind kind, CS_Status* status);
-CS_Source CreateCvSource(const wpi::Twine& name, const VideoMode& mode,
+CS_Source CreateCvSource(std::string_view name, const VideoMode& mode,
CS_Status* status);
/** @} */
@@ -215,21 +215,22 @@
*/
CS_SourceKind GetSourceKind(CS_Source source, CS_Status* status);
std::string GetSourceName(CS_Source source, CS_Status* status);
-wpi::StringRef GetSourceName(CS_Source source, wpi::SmallVectorImpl<char>& buf,
- CS_Status* status);
+std::string_view GetSourceName(CS_Source source,
+ wpi::SmallVectorImpl<char>& buf,
+ CS_Status* status);
std::string GetSourceDescription(CS_Source source, CS_Status* status);
-wpi::StringRef GetSourceDescription(CS_Source source,
- wpi::SmallVectorImpl<char>& buf,
- CS_Status* status);
+std::string_view GetSourceDescription(CS_Source source,
+ wpi::SmallVectorImpl<char>& buf,
+ CS_Status* status);
uint64_t GetSourceLastFrameTime(CS_Source source, CS_Status* status);
void SetSourceConnectionStrategy(CS_Source source,
CS_ConnectionStrategy strategy,
CS_Status* status);
bool IsSourceConnected(CS_Source source, CS_Status* status);
bool IsSourceEnabled(CS_Source source, CS_Status* status);
-CS_Property GetSourceProperty(CS_Source source, const wpi::Twine& name,
+CS_Property GetSourceProperty(CS_Source source, std::string_view name,
CS_Status* status);
-wpi::ArrayRef<CS_Property> EnumerateSourceProperties(
+wpi::span<CS_Property> EnumerateSourceProperties(
CS_Source source, wpi::SmallVectorImpl<CS_Property>& vec,
CS_Status* status);
VideoMode GetSourceVideoMode(CS_Source source, CS_Status* status);
@@ -240,7 +241,7 @@
bool SetSourceResolution(CS_Source source, int width, int height,
CS_Status* status);
bool SetSourceFPS(CS_Source source, int fps, CS_Status* status);
-bool SetSourceConfigJson(CS_Source source, wpi::StringRef config,
+bool SetSourceConfigJson(CS_Source source, std::string_view config,
CS_Status* status);
bool SetSourceConfigJson(CS_Source source, const wpi::json& config,
CS_Status* status);
@@ -248,9 +249,9 @@
wpi::json GetSourceConfigJsonObject(CS_Source source, CS_Status* status);
std::vector<VideoMode> EnumerateSourceVideoModes(CS_Source source,
CS_Status* status);
-wpi::ArrayRef<CS_Sink> EnumerateSourceSinks(CS_Source source,
- wpi::SmallVectorImpl<CS_Sink>& vec,
- CS_Status* status);
+wpi::span<CS_Sink> EnumerateSourceSinks(CS_Source source,
+ wpi::SmallVectorImpl<CS_Sink>& vec,
+ CS_Status* status);
CS_Source CopySource(CS_Source source, CS_Status* status);
void ReleaseSource(CS_Source source, CS_Status* status);
/** @} */
@@ -274,7 +275,7 @@
* @defgroup cscore_usbcamera_func UsbCamera Source Functions
* @{
*/
-void SetUsbCameraPath(CS_Source, const wpi::Twine& path, CS_Status* status);
+void SetUsbCameraPath(CS_Source, std::string_view path, CS_Status* status);
std::string GetUsbCameraPath(CS_Source source, CS_Status* status);
UsbCameraInfo GetUsbCameraInfo(CS_Source source, CS_Status* status);
/** @} */
@@ -284,7 +285,7 @@
* @{
*/
CS_HttpCameraKind GetHttpCameraKind(CS_Source source, CS_Status* status);
-void SetHttpCameraUrls(CS_Source source, wpi::ArrayRef<std::string> urls,
+void SetHttpCameraUrls(CS_Source source, wpi::span<const std::string> urls,
CS_Status* status);
std::vector<std::string> GetHttpCameraUrls(CS_Source source, CS_Status* status);
/** @} */
@@ -293,17 +294,17 @@
* @defgroup cscore_opencv_source_func OpenCV Source Functions
* @{
*/
-void NotifySourceError(CS_Source source, const wpi::Twine& msg,
+void NotifySourceError(CS_Source source, std::string_view msg,
CS_Status* status);
void SetSourceConnected(CS_Source source, bool connected, CS_Status* status);
-void SetSourceDescription(CS_Source source, const wpi::Twine& description,
+void SetSourceDescription(CS_Source source, std::string_view description,
CS_Status* status);
-CS_Property CreateSourceProperty(CS_Source source, const wpi::Twine& name,
+CS_Property CreateSourceProperty(CS_Source source, std::string_view name,
CS_PropertyKind kind, int minimum, int maximum,
int step, int defaultValue, int value,
CS_Status* status);
void SetSourceEnumPropertyChoices(CS_Source source, CS_Property property,
- wpi::ArrayRef<std::string> choices,
+ wpi::span<const std::string> choices,
CS_Status* status);
/** @} */
@@ -311,11 +312,10 @@
* @defgroup cscore_sink_create_func Sink Creation Functions
* @{
*/
-CS_Sink CreateMjpegServer(const wpi::Twine& name,
- const wpi::Twine& listenAddress, int port,
- CS_Status* status);
-CS_Sink CreateCvSink(const wpi::Twine& name, CS_Status* status);
-CS_Sink CreateCvSinkCallback(const wpi::Twine& name,
+CS_Sink CreateMjpegServer(std::string_view name, std::string_view listenAddress,
+ int port, CS_Status* status);
+CS_Sink CreateCvSink(std::string_view name, CS_Status* status);
+CS_Sink CreateCvSinkCallback(std::string_view name,
std::function<void(uint64_t time)> processFrame,
CS_Status* status);
@@ -327,19 +327,21 @@
*/
CS_SinkKind GetSinkKind(CS_Sink sink, CS_Status* status);
std::string GetSinkName(CS_Sink sink, CS_Status* status);
-wpi::StringRef GetSinkName(CS_Sink sink, wpi::SmallVectorImpl<char>& buf,
- CS_Status* status);
+std::string_view GetSinkName(CS_Sink sink, wpi::SmallVectorImpl<char>& buf,
+ CS_Status* status);
std::string GetSinkDescription(CS_Sink sink, CS_Status* status);
-wpi::StringRef GetSinkDescription(CS_Sink sink, wpi::SmallVectorImpl<char>& buf,
- CS_Status* status);
-CS_Property GetSinkProperty(CS_Sink sink, const wpi::Twine& name,
+std::string_view GetSinkDescription(CS_Sink sink,
+ wpi::SmallVectorImpl<char>& buf,
+ CS_Status* status);
+CS_Property GetSinkProperty(CS_Sink sink, std::string_view name,
CS_Status* status);
-wpi::ArrayRef<CS_Property> EnumerateSinkProperties(
+wpi::span<CS_Property> EnumerateSinkProperties(
CS_Sink sink, wpi::SmallVectorImpl<CS_Property>& vec, CS_Status* status);
void SetSinkSource(CS_Sink sink, CS_Source source, CS_Status* status);
-CS_Property GetSinkSourceProperty(CS_Sink sink, const wpi::Twine& name,
+CS_Property GetSinkSourceProperty(CS_Sink sink, std::string_view name,
CS_Status* status);
-bool SetSinkConfigJson(CS_Sink sink, wpi::StringRef config, CS_Status* status);
+bool SetSinkConfigJson(CS_Sink sink, std::string_view config,
+ CS_Status* status);
bool SetSinkConfigJson(CS_Sink sink, const wpi::json& config,
CS_Status* status);
std::string GetSinkConfigJson(CS_Sink sink, CS_Status* status);
@@ -361,11 +363,11 @@
* @defgroup cscore_opencv_sink_func OpenCV Sink Functions
* @{
*/
-void SetSinkDescription(CS_Sink sink, const wpi::Twine& description,
+void SetSinkDescription(CS_Sink sink, std::string_view description,
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);
+std::string_view GetSinkError(CS_Sink sink, wpi::SmallVectorImpl<char>& buf,
+ CS_Status* status);
void SetSinkEnabled(CS_Sink sink, bool enabled, CS_Status* status);
/** @} */
@@ -380,6 +382,15 @@
int eventMask, bool immediateNotify, CS_Status* status);
void RemoveListener(CS_Listener handle, CS_Status* status);
+
+CS_ListenerPoller CreateListenerPoller();
+void DestroyListenerPoller(CS_ListenerPoller poller);
+CS_Listener AddPolledListener(CS_ListenerPoller poller, int eventMask,
+ bool immediateNotify, CS_Status* status);
+std::vector<RawEvent> PollListener(CS_ListenerPoller poller);
+std::vector<RawEvent> PollListener(CS_ListenerPoller poller, double timeout,
+ bool* timedOut);
+void CancelPollListener(CS_ListenerPoller poller);
/** @} */
bool NotifierDestroyed();
@@ -419,10 +430,10 @@
*/
std::vector<UsbCameraInfo> EnumerateUsbCameras(CS_Status* status);
-wpi::ArrayRef<CS_Source> EnumerateSourceHandles(
+wpi::span<CS_Source> EnumerateSourceHandles(
wpi::SmallVectorImpl<CS_Source>& vec, CS_Status* status);
-wpi::ArrayRef<CS_Sink> EnumerateSinkHandles(wpi::SmallVectorImpl<CS_Sink>& vec,
- CS_Status* status);
+wpi::span<CS_Sink> EnumerateSinkHandles(wpi::SmallVectorImpl<CS_Sink>& vec,
+ CS_Status* status);
std::string GetHostname();
diff --git a/cscore/src/main/native/include/cscore_cv.h b/cscore/src/main/native/include/cscore_cv.h
index 650399b..30a356b 100644
--- a/cscore/src/main/native/include/cscore_cv.h
+++ b/cscore/src/main/native/include/cscore_cv.h
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#ifndef CSCORE_CSCORE_CV_H_
#define CSCORE_CSCORE_CV_H_
@@ -85,7 +82,7 @@
* @param name Source name (arbitrary unique identifier)
* @param mode Video mode being generated
*/
- CvSource(const wpi::Twine& name, const VideoMode& mode);
+ CvSource(std::string_view name, const VideoMode& mode);
/**
* Create an OpenCV source.
@@ -96,8 +93,8 @@
* @param height height
* @param fps fps
*/
- CvSource(const wpi::Twine& name, VideoMode::PixelFormat pixelFormat,
- int width, int height, int fps);
+ CvSource(std::string_view name, VideoMode::PixelFormat pixelFormat, int width,
+ int height, int fps);
/**
* Put an OpenCV image and notify sinks.
@@ -129,7 +126,7 @@
*
* @param name Source name (arbitrary unique identifier)
*/
- explicit CvSink(const wpi::Twine& name);
+ explicit CvSink(std::string_view name);
/**
* Create a sink for accepting OpenCV images in a separate thread.
@@ -143,7 +140,7 @@
* or GetError() as needed, but should not call (except in very
* unusual circumstances) WaitForImage().
*/
- CvSink(const wpi::Twine& name,
+ CvSink(std::string_view name,
std::function<void(uint64_t time)> processFrame);
/**
@@ -155,7 +152,8 @@
* 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;
+ [[nodiscard]] uint64_t GrabFrame(cv::Mat& image,
+ double timeout = 0.225) const;
/**
* Wait for the next frame and get the image. May block forever.
@@ -165,14 +163,14 @@
* 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;
+ [[nodiscard]] uint64_t GrabFrameNoTimeout(cv::Mat& image) const;
};
-inline CvSource::CvSource(const wpi::Twine& name, const VideoMode& mode) {
+inline CvSource::CvSource(std::string_view name, const VideoMode& mode) {
m_handle = CreateCvSource(name, mode, &m_status);
}
-inline CvSource::CvSource(const wpi::Twine& name, VideoMode::PixelFormat format,
+inline CvSource::CvSource(std::string_view name, VideoMode::PixelFormat format,
int width, int height, int fps) {
m_handle =
CreateCvSource(name, VideoMode{format, width, height, fps}, &m_status);
@@ -183,11 +181,11 @@
PutSourceFrame(m_handle, image, &m_status);
}
-inline CvSink::CvSink(const wpi::Twine& name) {
+inline CvSink::CvSink(std::string_view name) {
m_handle = CreateCvSink(name, &m_status);
}
-inline CvSink::CvSink(const wpi::Twine& name,
+inline CvSink::CvSink(std::string_view name,
std::function<void(uint64_t time)> processFrame) {
m_handle = CreateCvSinkCallback(name, processFrame, &m_status);
}
diff --git a/cscore/src/main/native/include/cscore_oo.h b/cscore/src/main/native/include/cscore_oo.h
index 9e6e290..4fd1bff 100644
--- a/cscore/src/main/native/include/cscore_oo.h
+++ b/cscore/src/main/native/include/cscore_oo.h
@@ -1,18 +1,18 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2015-2020 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#ifndef CSCORE_CSCORE_OO_H_
#define CSCORE_CSCORE_OO_H_
#include <initializer_list>
#include <string>
+#include <string_view>
#include <utility>
#include <vector>
+#include <wpi/span.h>
+
#include "cscore_cpp.h"
namespace cs {
@@ -51,7 +51,7 @@
kEnum = CS_PROP_ENUM
};
- VideoProperty() : m_status(0), m_handle(0), m_kind(kNone) {}
+ VideoProperty() = default;
std::string GetName() const;
@@ -74,8 +74,8 @@
// String-specific functions
std::string GetString() const;
- wpi::StringRef GetString(wpi::SmallVectorImpl<char>& buf) const;
- void SetString(const wpi::Twine& value);
+ std::string_view GetString(wpi::SmallVectorImpl<char>& buf) const;
+ void SetString(std::string_view value);
// Enum-specific functions
std::vector<std::string> GetChoices() const;
@@ -86,9 +86,9 @@
explicit VideoProperty(CS_Property handle);
VideoProperty(CS_Property handle, Kind kind);
- mutable CS_Status m_status;
- CS_Property m_handle;
- Kind m_kind;
+ mutable CS_Status m_status{0};
+ CS_Property m_handle{0};
+ Kind m_kind{kNone};
};
/**
@@ -127,7 +127,7 @@
kConnectionForceClose = CS_CONNECTION_FORCE_CLOSE
};
- VideoSource() noexcept : m_handle(0) {}
+ VideoSource() noexcept = default;
VideoSource(const VideoSource& source);
VideoSource(VideoSource&& other) noexcept;
VideoSource& operator=(VideoSource other) noexcept;
@@ -197,7 +197,7 @@
* @return Property contents (of kind Property::kNone if no property with
* the given name exists)
*/
- VideoProperty GetProperty(const wpi::Twine& name);
+ VideoProperty GetProperty(std::string_view name);
/**
* Enumerate all properties of this source.
@@ -279,7 +279,7 @@
* @param config configuration
* @return True if set successfully
*/
- bool SetConfigJson(wpi::StringRef config);
+ bool SetConfigJson(std::string_view config);
/**
* Set video mode and properties from a JSON configuration object.
@@ -352,7 +352,7 @@
explicit VideoSource(CS_Source handle) : m_handle(handle) {}
mutable CS_Status m_status = 0;
- CS_Source m_handle;
+ CS_Source m_handle{0};
};
/**
@@ -427,7 +427,7 @@
* @param name Source name (arbitrary unique identifier)
* @param dev Device number (e.g. 0 for /dev/video0)
*/
- UsbCamera(const wpi::Twine& name, int dev);
+ UsbCamera(std::string_view name, int dev);
/**
* Create a source for a USB camera based on device path.
@@ -435,7 +435,7 @@
* @param name Source name (arbitrary unique identifier)
* @param path Path to device (e.g. "/dev/video0" on Linux)
*/
- UsbCamera(const wpi::Twine& name, const wpi::Twine& path);
+ UsbCamera(std::string_view name, std::string_view path);
/**
* Enumerate USB cameras on the local system.
@@ -447,7 +447,7 @@
/**
* Change the path to the device.
*/
- void SetPath(const wpi::Twine& path);
+ void SetPath(std::string_view path);
/**
* Get the path to the device.
@@ -486,7 +486,7 @@
* @param url Camera URL (e.g. "http://10.x.y.11/video/stream.mjpg")
* @param kind Camera kind (e.g. kAxis)
*/
- HttpCamera(const wpi::Twine& name, const wpi::Twine& url,
+ HttpCamera(std::string_view name, std::string_view url,
HttpCameraKind kind = kUnknown);
/**
@@ -496,7 +496,7 @@
* @param url Camera URL (e.g. "http://10.x.y.11/video/stream.mjpg")
* @param kind Camera kind (e.g. kAxis)
*/
- HttpCamera(const wpi::Twine& name, const char* url,
+ HttpCamera(std::string_view name, const char* url,
HttpCameraKind kind = kUnknown);
/**
@@ -506,7 +506,7 @@
* @param url Camera URL (e.g. "http://10.x.y.11/video/stream.mjpg")
* @param kind Camera kind (e.g. kAxis)
*/
- HttpCamera(const wpi::Twine& name, const std::string& url,
+ HttpCamera(std::string_view name, const std::string& url,
HttpCameraKind kind = kUnknown);
/**
@@ -516,7 +516,7 @@
* @param urls Array of Camera URLs
* @param kind Camera kind (e.g. kAxis)
*/
- HttpCamera(const wpi::Twine& name, wpi::ArrayRef<std::string> urls,
+ HttpCamera(std::string_view name, wpi::span<const std::string> urls,
HttpCameraKind kind = kUnknown);
/**
@@ -527,7 +527,7 @@
* @param kind Camera kind (e.g. kAxis)
*/
template <typename T>
- HttpCamera(const wpi::Twine& name, std::initializer_list<T> urls,
+ HttpCamera(std::string_view name, std::initializer_list<T> urls,
HttpCameraKind kind = kUnknown);
/**
@@ -541,7 +541,7 @@
/**
* Change the URLs used to connect to the camera.
*/
- void SetUrls(wpi::ArrayRef<std::string> urls);
+ void SetUrls(wpi::span<const std::string> urls);
/**
* Change the URLs used to connect to the camera.
@@ -559,8 +559,8 @@
* A source that represents an Axis IP camera.
*/
class AxisCamera : public HttpCamera {
- static std::string HostToUrl(const wpi::Twine& host);
- static std::vector<std::string> HostToUrl(wpi::ArrayRef<std::string> hosts);
+ static std::string HostToUrl(std::string_view host);
+ static std::vector<std::string> HostToUrl(wpi::span<const std::string> hosts);
template <typename T>
static std::vector<std::string> HostToUrl(std::initializer_list<T> hosts);
@@ -570,55 +570,41 @@
*
* @param name Source name (arbitrary unique identifier)
* @param host Camera host IP or DNS name (e.g. "10.x.y.11")
- * @param kind Camera kind (e.g. kAxis)
*/
- AxisCamera(const wpi::Twine& name, const wpi::Twine& host);
+ AxisCamera(std::string_view name, std::string_view host);
/**
* Create a source for an Axis IP camera.
*
* @param name Source name (arbitrary unique identifier)
* @param host Camera host IP or DNS name (e.g. "10.x.y.11")
- * @param kind Camera kind (e.g. kAxis)
*/
- AxisCamera(const wpi::Twine& name, const char* host);
+ AxisCamera(std::string_view name, const char* host);
/**
* Create a source for an Axis IP camera.
*
* @param name Source name (arbitrary unique identifier)
* @param host Camera host IP or DNS name (e.g. "10.x.y.11")
- * @param kind Camera kind (e.g. kAxis)
*/
- AxisCamera(const wpi::Twine& name, const std::string& host);
-
- /**
- * Create a source for an Axis IP camera.
- *
- * @param name Source name (arbitrary unique identifier)
- * @param host Camera host IP or DNS name (e.g. "10.x.y.11")
- * @param kind Camera kind (e.g. kAxis)
- */
- AxisCamera(const wpi::Twine& name, wpi::StringRef host);
+ AxisCamera(std::string_view name, const std::string& host);
/**
* Create a source for an Axis IP camera.
*
* @param name Source name (arbitrary unique identifier)
* @param hosts Array of Camera host IPs/DNS names
- * @param kind Camera kind (e.g. kAxis)
*/
- AxisCamera(const wpi::Twine& name, wpi::ArrayRef<std::string> hosts);
+ AxisCamera(std::string_view name, wpi::span<const std::string> hosts);
/**
* Create a source for an Axis IP camera.
*
* @param name Source name (arbitrary unique identifier)
* @param hosts Array of Camera host IPs/DNS names
- * @param kind Camera kind (e.g. kAxis)
*/
template <typename T>
- AxisCamera(const wpi::Twine& name, std::initializer_list<T> hosts);
+ AxisCamera(std::string_view name, std::initializer_list<T> hosts);
};
/**
@@ -632,8 +618,10 @@
/**
* Signal sinks that an error has occurred. This should be called instead
* of NotifyFrame when an error occurs.
+ *
+ * @param msg Notification message.
*/
- void NotifyError(const wpi::Twine& msg);
+ void NotifyError(std::string_view msg);
/**
* Set source connection status. Defaults to true.
@@ -647,7 +635,7 @@
*
* @param description Description
*/
- void SetDescription(const wpi::Twine& description);
+ void SetDescription(std::string_view description);
/**
* Create a property.
@@ -661,7 +649,7 @@
* @param value Current value
* @return Property
*/
- VideoProperty CreateProperty(const wpi::Twine& name, VideoProperty::Kind kind,
+ VideoProperty CreateProperty(std::string_view name, VideoProperty::Kind kind,
int minimum, int maximum, int step,
int defaultValue, int value);
@@ -676,7 +664,7 @@
* @param value Current value
* @return Property
*/
- VideoProperty CreateIntegerProperty(const wpi::Twine& name, int minimum,
+ VideoProperty CreateIntegerProperty(std::string_view name, int minimum,
int maximum, int step, int defaultValue,
int value);
@@ -688,19 +676,18 @@
* @param value Current value
* @return Property
*/
- VideoProperty CreateBooleanProperty(const wpi::Twine& name, bool defaultValue,
+ VideoProperty CreateBooleanProperty(std::string_view name, bool defaultValue,
bool value);
/**
* Create a string property.
*
* @param name Property name
- * @param defaultValue Default value
* @param value Current value
* @return Property
*/
- VideoProperty CreateStringProperty(const wpi::Twine& name,
- const wpi::Twine& value);
+ VideoProperty CreateStringProperty(std::string_view name,
+ std::string_view value);
/**
* Configure enum property choices.
@@ -709,7 +696,7 @@
* @param choices Choices
*/
void SetEnumPropertyChoices(const VideoProperty& property,
- wpi::ArrayRef<std::string> choices);
+ wpi::span<const std::string> choices);
/**
* Configure enum property choices.
@@ -736,7 +723,7 @@
kCv = CS_SINK_CV
};
- VideoSink() noexcept : m_handle(0) {}
+ VideoSink() noexcept = default;
VideoSink(const VideoSink& sink);
VideoSink(VideoSink&& sink) noexcept;
VideoSink& operator=(VideoSink other) noexcept;
@@ -775,7 +762,7 @@
* @return Property (kind Property::kNone if no property with
* the given name exists)
*/
- VideoProperty GetProperty(const wpi::Twine& name);
+ VideoProperty GetProperty(std::string_view name);
/**
* Enumerate all properties of this sink.
@@ -801,7 +788,7 @@
* @param config configuration
* @return True if set successfully
*/
- bool SetConfigJson(wpi::StringRef config);
+ bool SetConfigJson(std::string_view config);
/**
* Set properties from a JSON configuration object.
@@ -848,7 +835,7 @@
* @return Property (kind Property::kNone if no property with
* the given name exists or no source connected)
*/
- VideoProperty GetSourceProperty(const wpi::Twine& name);
+ VideoProperty GetSourceProperty(std::string_view name);
CS_Status GetLastStatus() const { return m_status; }
@@ -869,7 +856,7 @@
explicit VideoSink(CS_Sink handle) : m_handle(handle) {}
mutable CS_Status m_status = 0;
- CS_Sink m_handle;
+ CS_Sink m_handle{0};
};
/**
@@ -886,8 +873,7 @@
* @param listenAddress TCP listen address (empty string for all addresses)
* @param port TCP port number
*/
- MjpegServer(const wpi::Twine& name, const wpi::Twine& listenAddress,
- int port);
+ MjpegServer(std::string_view name, std::string_view listenAddress, int port);
/**
* Create a MJPEG-over-HTTP server sink.
@@ -895,7 +881,7 @@
* @param name Sink name (arbitrary unique identifier)
* @param port TCP port number
*/
- MjpegServer(const wpi::Twine& name, int port) : MjpegServer(name, "", port) {}
+ MjpegServer(std::string_view name, int port) : MjpegServer(name, "", port) {}
/**
* Get the listen address of the server.
@@ -966,7 +952,7 @@
*
* @param description Description
*/
- void SetDescription(const wpi::Twine& description);
+ void SetDescription(std::string_view description);
/**
* Get error string. Call this if WaitForFrame() returns 0 to determine
@@ -1011,7 +997,7 @@
*/
class VideoListener {
public:
- VideoListener() : m_handle(0) {}
+ VideoListener() = default;
/**
* Create an event listener.
@@ -1036,13 +1022,13 @@
}
private:
- CS_Listener m_handle;
+ CS_Listener m_handle{0};
};
/** @} */
} // namespace cs
-#include "cscore_oo.inl"
+#include "cscore_oo.inc"
#endif // CSCORE_CSCORE_OO_H_
diff --git a/cscore/src/main/native/include/cscore_oo.inl b/cscore/src/main/native/include/cscore_oo.inc
similarity index 79%
rename from cscore/src/main/native/include/cscore_oo.inl
rename to cscore/src/main/native/include/cscore_oo.inc
index 2d56e1c..5037d97 100644
--- a/cscore/src/main/native/include/cscore_oo.inl
+++ b/cscore/src/main/native/include/cscore_oo.inc
@@ -1,17 +1,17 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2015-2020 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
-#ifndef CSCORE_CSCORE_OO_INL_
-#define CSCORE_CSCORE_OO_INL_
+#ifndef CSCORE_CSCORE_OO_INC_
+#define CSCORE_CSCORE_OO_INC_
#include <string>
+#include <string_view>
#include <utility>
#include <vector>
+#include "cscore_oo.h"
+
namespace cs {
inline std::string VideoProperty::GetName() const {
@@ -54,13 +54,13 @@
return GetStringProperty(m_handle, &m_status);
}
-inline wpi::StringRef VideoProperty::GetString(
+inline std::string_view VideoProperty::GetString(
wpi::SmallVectorImpl<char>& buf) const {
m_status = 0;
return GetStringProperty(m_handle, buf, &m_status);
}
-inline void VideoProperty::SetString(const wpi::Twine& value) {
+inline void VideoProperty::SetString(std::string_view value) {
m_status = 0;
SetStringProperty(m_handle, value, &m_status);
}
@@ -72,15 +72,16 @@
inline VideoProperty::VideoProperty(CS_Property handle) : m_handle(handle) {
m_status = 0;
- if (handle == 0)
+ if (handle == 0) {
m_kind = kNone;
- else
+ } else {
m_kind =
static_cast<Kind>(static_cast<int>(GetPropertyKind(handle, &m_status)));
+ }
}
inline VideoProperty::VideoProperty(CS_Property handle, Kind kind)
- : m_status(0), m_handle(handle), m_kind(kind) {}
+ : m_handle(handle), m_kind(kind) {}
inline VideoSource::VideoSource(const VideoSource& source)
: m_handle(source.m_handle == 0 ? 0
@@ -97,7 +98,9 @@
inline VideoSource::~VideoSource() {
m_status = 0;
- if (m_handle != 0) ReleaseSource(m_handle, &m_status);
+ if (m_handle != 0) {
+ ReleaseSource(m_handle, &m_status);
+ }
}
inline VideoSource::Kind VideoSource::GetKind() const {
@@ -137,7 +140,7 @@
return IsSourceEnabled(m_handle, &m_status);
}
-inline VideoProperty VideoSource::GetProperty(const wpi::Twine& name) {
+inline VideoProperty VideoSource::GetProperty(std::string_view name) {
m_status = 0;
return VideoProperty{GetSourceProperty(m_handle, name, &m_status)};
}
@@ -174,7 +177,7 @@
return SetSourceFPS(m_handle, fps, &m_status);
}
-inline bool VideoSource::SetConfigJson(wpi::StringRef config) {
+inline bool VideoSource::SetConfigJson(std::string_view config) {
m_status = 0;
return SetSourceConfigJson(m_handle, config, &m_status);
}
@@ -246,11 +249,11 @@
SetCameraExposureManual(m_handle, value, &m_status);
}
-inline UsbCamera::UsbCamera(const wpi::Twine& name, int dev) {
+inline UsbCamera::UsbCamera(std::string_view name, int dev) {
m_handle = CreateUsbCameraDev(name, dev, &m_status);
}
-inline UsbCamera::UsbCamera(const wpi::Twine& name, const wpi::Twine& path) {
+inline UsbCamera::UsbCamera(std::string_view name, std::string_view path) {
m_handle = CreateUsbCameraPath(name, path, &m_status);
}
@@ -259,7 +262,7 @@
return ::cs::EnumerateUsbCameras(&status);
}
-inline void UsbCamera::SetPath(const wpi::Twine& path) {
+inline void UsbCamera::SetPath(std::string_view path) {
m_status = 0;
return ::cs::SetUsbCameraPath(m_handle, path, &m_status);
}
@@ -280,26 +283,26 @@
&m_status);
}
-inline HttpCamera::HttpCamera(const wpi::Twine& name, const wpi::Twine& url,
+inline HttpCamera::HttpCamera(std::string_view name, std::string_view url,
HttpCameraKind kind) {
m_handle = CreateHttpCamera(
name, url, static_cast<CS_HttpCameraKind>(static_cast<int>(kind)),
&m_status);
}
-inline HttpCamera::HttpCamera(const wpi::Twine& name, const char* url,
+inline HttpCamera::HttpCamera(std::string_view name, const char* url,
HttpCameraKind kind) {
m_handle = CreateHttpCamera(
name, url, static_cast<CS_HttpCameraKind>(static_cast<int>(kind)),
&m_status);
}
-inline HttpCamera::HttpCamera(const wpi::Twine& name, const std::string& url,
+inline HttpCamera::HttpCamera(std::string_view name, const std::string& url,
HttpCameraKind kind)
- : HttpCamera(name, wpi::Twine{url}, kind) {}
+ : HttpCamera(name, std::string_view{url}, kind) {}
-inline HttpCamera::HttpCamera(const wpi::Twine& name,
- wpi::ArrayRef<std::string> urls,
+inline HttpCamera::HttpCamera(std::string_view name,
+ wpi::span<const std::string> urls,
HttpCameraKind kind) {
m_handle = CreateHttpCamera(
name, urls, static_cast<CS_HttpCameraKind>(static_cast<int>(kind)),
@@ -307,12 +310,14 @@
}
template <typename T>
-inline HttpCamera::HttpCamera(const wpi::Twine& name,
+inline HttpCamera::HttpCamera(std::string_view name,
std::initializer_list<T> urls,
HttpCameraKind kind) {
std::vector<std::string> vec;
vec.reserve(urls.size());
- for (const auto& url : urls) vec.emplace_back(url);
+ for (const auto& url : urls) {
+ vec.emplace_back(url);
+ }
m_handle = CreateHttpCamera(
name, vec, static_cast<CS_HttpCameraKind>(static_cast<int>(kind)),
&m_status);
@@ -324,7 +329,7 @@
static_cast<int>(::cs::GetHttpCameraKind(m_handle, &m_status)));
}
-inline void HttpCamera::SetUrls(wpi::ArrayRef<std::string> urls) {
+inline void HttpCamera::SetUrls(wpi::span<const std::string> urls) {
m_status = 0;
::cs::SetHttpCameraUrls(m_handle, urls, &m_status);
}
@@ -333,7 +338,9 @@
inline void HttpCamera::SetUrls(std::initializer_list<T> urls) {
std::vector<std::string> vec;
vec.reserve(urls.size());
- for (const auto& url : urls) vec.emplace_back(url);
+ for (const auto& url : urls) {
+ vec.emplace_back(url);
+ }
m_status = 0;
::cs::SetHttpCameraUrls(m_handle, vec, &m_status);
}
@@ -343,16 +350,13 @@
return ::cs::GetHttpCameraUrls(m_handle, &m_status);
}
-inline std::string AxisCamera::HostToUrl(const wpi::Twine& host) {
- return ("http://" + host + "/mjpg/video.mjpg").str();
-}
-
inline std::vector<std::string> AxisCamera::HostToUrl(
- wpi::ArrayRef<std::string> hosts) {
+ wpi::span<const std::string> hosts) {
std::vector<std::string> rv;
rv.reserve(hosts.size());
- for (const auto& host : hosts)
- rv.emplace_back(HostToUrl(wpi::StringRef{host}));
+ for (const auto& host : hosts) {
+ rv.emplace_back(HostToUrl(std::string_view{host}));
+ }
return rv;
}
@@ -361,33 +365,31 @@
std::initializer_list<T> hosts) {
std::vector<std::string> rv;
rv.reserve(hosts.size());
- for (const auto& host : hosts)
- rv.emplace_back(HostToUrl(wpi::StringRef{host}));
+ for (const auto& host : hosts) {
+ rv.emplace_back(HostToUrl(std::string_view{host}));
+ }
return rv;
}
-inline AxisCamera::AxisCamera(const wpi::Twine& name, const wpi::Twine& host)
+inline AxisCamera::AxisCamera(std::string_view name, std::string_view host)
: HttpCamera(name, HostToUrl(host), kAxis) {}
-inline AxisCamera::AxisCamera(const wpi::Twine& name, const char* host)
+inline AxisCamera::AxisCamera(std::string_view name, const char* host)
: HttpCamera(name, HostToUrl(host), kAxis) {}
-inline AxisCamera::AxisCamera(const wpi::Twine& name, const std::string& host)
- : HttpCamera(name, HostToUrl(wpi::Twine{host}), kAxis) {}
+inline AxisCamera::AxisCamera(std::string_view name, const std::string& host)
+ : HttpCamera(name, HostToUrl(std::string_view{host}), kAxis) {}
-inline AxisCamera::AxisCamera(const wpi::Twine& name, wpi::StringRef host)
- : HttpCamera(name, HostToUrl(host), kAxis) {}
-
-inline AxisCamera::AxisCamera(const wpi::Twine& name,
- wpi::ArrayRef<std::string> hosts)
+inline AxisCamera::AxisCamera(std::string_view name,
+ wpi::span<const std::string> hosts)
: HttpCamera(name, HostToUrl(hosts), kAxis) {}
template <typename T>
-inline AxisCamera::AxisCamera(const wpi::Twine& name,
+inline AxisCamera::AxisCamera(std::string_view name,
std::initializer_list<T> hosts)
: HttpCamera(name, HostToUrl(hosts), kAxis) {}
-inline void ImageSource::NotifyError(const wpi::Twine& msg) {
+inline void ImageSource::NotifyError(std::string_view msg) {
m_status = 0;
NotifySourceError(m_handle, msg, &m_status);
}
@@ -397,12 +399,12 @@
SetSourceConnected(m_handle, connected, &m_status);
}
-inline void ImageSource::SetDescription(const wpi::Twine& description) {
+inline void ImageSource::SetDescription(std::string_view description) {
m_status = 0;
SetSourceDescription(m_handle, description, &m_status);
}
-inline VideoProperty ImageSource::CreateProperty(const wpi::Twine& name,
+inline VideoProperty ImageSource::CreateProperty(std::string_view name,
VideoProperty::Kind kind,
int minimum, int maximum,
int step, int defaultValue,
@@ -413,7 +415,7 @@
minimum, maximum, step, defaultValue, value, &m_status)};
}
-inline VideoProperty ImageSource::CreateIntegerProperty(const wpi::Twine& name,
+inline VideoProperty ImageSource::CreateIntegerProperty(std::string_view name,
int minimum,
int maximum, int step,
int defaultValue,
@@ -426,7 +428,7 @@
minimum, maximum, step, defaultValue, value, &m_status)};
}
-inline VideoProperty ImageSource::CreateBooleanProperty(const wpi::Twine& name,
+inline VideoProperty ImageSource::CreateBooleanProperty(std::string_view name,
bool defaultValue,
bool value) {
m_status = 0;
@@ -437,8 +439,8 @@
0, 1, 1, defaultValue ? 1 : 0, value ? 1 : 0, &m_status)};
}
-inline VideoProperty ImageSource::CreateStringProperty(
- const wpi::Twine& name, const wpi::Twine& value) {
+inline VideoProperty ImageSource::CreateStringProperty(std::string_view name,
+ std::string_view value) {
m_status = 0;
auto prop = VideoProperty{
CreateSourceProperty(m_handle, name,
@@ -450,7 +452,7 @@
}
inline void ImageSource::SetEnumPropertyChoices(
- const VideoProperty& property, wpi::ArrayRef<std::string> choices) {
+ const VideoProperty& property, wpi::span<const std::string> choices) {
m_status = 0;
SetSourceEnumPropertyChoices(m_handle, property.m_handle, choices, &m_status);
}
@@ -460,7 +462,9 @@
const VideoProperty& property, std::initializer_list<T> choices) {
std::vector<std::string> vec;
vec.reserve(choices.size());
- for (const auto& choice : choices) vec.emplace_back(choice);
+ for (const auto& choice : choices) {
+ vec.emplace_back(choice);
+ }
m_status = 0;
SetSourceEnumPropertyChoices(m_handle, property.m_handle, vec, &m_status);
}
@@ -479,7 +483,9 @@
inline VideoSink::~VideoSink() {
m_status = 0;
- if (m_handle != 0) ReleaseSink(m_handle, &m_status);
+ if (m_handle != 0) {
+ ReleaseSink(m_handle, &m_status);
+ }
}
inline VideoSink::Kind VideoSink::GetKind() const {
@@ -497,17 +503,18 @@
return GetSinkDescription(m_handle, &m_status);
}
-inline VideoProperty VideoSink::GetProperty(const wpi::Twine& name) {
+inline VideoProperty VideoSink::GetProperty(std::string_view name) {
m_status = 0;
return VideoProperty{GetSinkProperty(m_handle, name, &m_status)};
}
inline void VideoSink::SetSource(VideoSource source) {
m_status = 0;
- if (!source)
+ if (!source) {
SetSinkSource(m_handle, 0, &m_status);
- else
+ } else {
SetSinkSource(m_handle, source.m_handle, &m_status);
+ }
}
inline VideoSource VideoSink::GetSource() const {
@@ -516,12 +523,12 @@
return VideoSource{handle == 0 ? 0 : CopySource(handle, &m_status)};
}
-inline VideoProperty VideoSink::GetSourceProperty(const wpi::Twine& name) {
+inline VideoProperty VideoSink::GetSourceProperty(std::string_view name) {
m_status = 0;
return VideoProperty{GetSinkSourceProperty(m_handle, name, &m_status)};
}
-inline bool VideoSink::SetConfigJson(wpi::StringRef config) {
+inline bool VideoSink::SetConfigJson(std::string_view config) {
m_status = 0;
return SetSinkConfigJson(m_handle, config, &m_status);
}
@@ -536,8 +543,8 @@
return GetSinkConfigJson(m_handle, &m_status);
}
-inline MjpegServer::MjpegServer(const wpi::Twine& name,
- const wpi::Twine& listenAddress, int port) {
+inline MjpegServer::MjpegServer(std::string_view name,
+ std::string_view listenAddress, int port) {
m_handle = CreateMjpegServer(name, listenAddress, port, &m_status);
}
@@ -575,7 +582,7 @@
quality, &m_status);
}
-inline void ImageSink::SetDescription(const wpi::Twine& description) {
+inline void ImageSink::SetDescription(std::string_view description) {
m_status = 0;
SetSinkDescription(m_handle, description, &m_status);
}
@@ -628,9 +635,11 @@
inline VideoListener::~VideoListener() {
CS_Status status = 0;
- if (m_handle != 0) RemoveListener(m_handle, &status);
+ if (m_handle != 0) {
+ RemoveListener(m_handle, &status);
+ }
}
} // namespace cs
-#endif // CSCORE_CSCORE_OO_INL_
+#endif // CSCORE_CSCORE_OO_INC_
diff --git a/cscore/src/main/native/include/cscore_raw.h b/cscore/src/main/native/include/cscore_raw.h
index 902d90e..0aaaeff 100644
--- a/cscore/src/main/native/include/cscore_raw.h
+++ b/cscore/src/main/native/include/cscore_raw.h
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#ifndef CSCORE_CSCORE_RAW_H_
#define CSCORE_CSCORE_RAW_H_
@@ -17,7 +14,7 @@
/**
* Raw Frame
*/
-typedef struct CS_RawFrame {
+typedef struct CS_RawFrame { // NOLINT
char* data;
int dataLength;
int pixelFormat;
@@ -81,11 +78,11 @@
* @{
*/
-CS_Source CreateRawSource(const wpi::Twine& name, const VideoMode& mode,
+CS_Source CreateRawSource(std::string_view name, const VideoMode& mode,
CS_Status* status);
-CS_Sink CreateRawSink(const wpi::Twine& name, CS_Status* status);
-CS_Sink CreateRawSinkCallback(const wpi::Twine& name,
+CS_Sink CreateRawSink(std::string_view name, CS_Status* status);
+CS_Sink CreateRawSinkCallback(std::string_view name,
std::function<void(uint64_t time)> processFrame,
CS_Status* status);
@@ -110,7 +107,7 @@
* @param name Source name (arbitrary unique identifier)
* @param mode Video mode being generated
*/
- RawSource(const wpi::Twine& name, const VideoMode& mode);
+ RawSource(std::string_view name, const VideoMode& mode);
/**
* Create a raw frame source.
@@ -121,7 +118,7 @@
* @param height height
* @param fps fps
*/
- RawSource(const wpi::Twine& name, VideoMode::PixelFormat pixelFormat,
+ RawSource(std::string_view name, VideoMode::PixelFormat pixelFormat,
int width, int height, int fps);
protected:
@@ -150,7 +147,7 @@
*
* @param name Source name (arbitrary unique identifier)
*/
- explicit RawSink(const wpi::Twine& name);
+ explicit RawSink(std::string_view name);
/**
* Create a sink for accepting raws images in a separate thread.
@@ -164,7 +161,7 @@
* or GetError() as needed, but should not call (except in very
* unusual circumstances) WaitForImage().
*/
- RawSink(const wpi::Twine& name,
+ RawSink(std::string_view name,
std::function<void(uint64_t time)> processFrame);
protected:
@@ -177,7 +174,8 @@
* 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;
+ [[nodiscard]] uint64_t GrabFrame(RawFrame& image,
+ double timeout = 0.225) const;
/**
* Wait for the next frame and get the image. May block forever.
@@ -187,14 +185,14 @@
* 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;
+ [[nodiscard]] uint64_t GrabFrameNoTimeout(RawFrame& image) const;
};
-inline RawSource::RawSource(const wpi::Twine& name, const VideoMode& mode) {
+inline RawSource::RawSource(std::string_view name, const VideoMode& mode) {
m_handle = CreateRawSource(name, mode, &m_status);
}
-inline RawSource::RawSource(const wpi::Twine& name,
+inline RawSource::RawSource(std::string_view name,
VideoMode::PixelFormat format, int width,
int height, int fps) {
m_handle =
@@ -206,11 +204,11 @@
PutSourceFrame(m_handle, image, &m_status);
}
-inline RawSink::RawSink(const wpi::Twine& name) {
+inline RawSink::RawSink(std::string_view name) {
m_handle = CreateRawSink(name, &m_status);
}
-inline RawSink::RawSink(const wpi::Twine& name,
+inline RawSink::RawSink(std::string_view name,
std::function<void(uint64_t time)> processFrame) {
m_handle = CreateRawSinkCallback(name, processFrame, &m_status);
}
diff --git a/cscore/src/main/native/include/cscore_raw_cv.h b/cscore/src/main/native/include/cscore_raw_cv.h
index ed40006..5b9a374 100644
--- a/cscore/src/main/native/include/cscore_raw_cv.h
+++ b/cscore/src/main/native/include/cscore_raw_cv.h
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#ifndef CSCORE_CSCORE_RAW_CV_H_
#define CSCORE_CSCORE_RAW_CV_H_
@@ -12,6 +9,8 @@
#error "Cannot include both cscore_cv.h and cscore_raw_cv.h in the same file"
#endif
+#include <opencv2/core/mat.hpp>
+
#include "cscore_raw.h"
namespace cs {
@@ -35,7 +34,7 @@
* @param name Source name (arbitrary unique identifier)
* @param mode Video mode being generated
*/
- RawCvSource(const wpi::Twine& name, const VideoMode& mode);
+ RawCvSource(std::string_view name, const VideoMode& mode);
/**
* Create a Raw OpenCV source.
@@ -46,7 +45,7 @@
* @param height height
* @param fps fps
*/
- RawCvSource(const wpi::Twine& name, VideoMode::PixelFormat pixelFormat,
+ RawCvSource(std::string_view name, VideoMode::PixelFormat pixelFormat,
int width, int height, int fps);
/**
@@ -86,7 +85,7 @@
*
* @param name Source name (arbitrary unique identifier)
*/
- explicit RawCvSink(const wpi::Twine& name);
+ explicit RawCvSink(std::string_view name);
/**
* Create a sink for accepting OpenCV images in a separate thread.
@@ -100,7 +99,7 @@
* or GetError() as needed, but should not call (except in very
* unusual circumstances) WaitForImage().
*/
- RawCvSink(const wpi::Twine& name,
+ RawCvSink(std::string_view name,
std::function<void(uint64_t time)> processFrame);
/**
@@ -112,7 +111,7 @@
* 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);
+ [[nodiscard]] uint64_t GrabFrame(cv::Mat& image, double timeout = 0.225);
/**
* Wait for the next frame and get the image. May block forever.
@@ -122,7 +121,7 @@
* 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);
+ [[nodiscard]] uint64_t GrabFrameNoTimeout(cv::Mat& image);
/**
* Wait for the next frame and get the image.
@@ -133,7 +132,8 @@
* 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);
+ [[nodiscard]] uint64_t GrabFrameDirect(cv::Mat& image,
+ double timeout = 0.225);
/**
* Wait for the next frame and get the image. May block forever.
@@ -143,16 +143,16 @@
* 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);
+ [[nodiscard]] uint64_t GrabFrameNoTimeoutDirect(cv::Mat& image);
private:
RawFrame rawFrame;
};
-inline RawCvSource::RawCvSource(const wpi::Twine& name, const VideoMode& mode)
+inline RawCvSource::RawCvSource(std::string_view name, const VideoMode& mode)
: RawSource{name, mode} {}
-inline RawCvSource::RawCvSource(const wpi::Twine& name,
+inline RawCvSource::RawCvSource(std::string_view name,
VideoMode::PixelFormat format, int width,
int height, int fps)
: RawSource{name, format, width, height, fps} {}
@@ -162,34 +162,34 @@
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;
+ 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(std::string_view name) : RawSink{name} {}
-inline RawCvSink::RawCvSink(const wpi::Twine& name,
+inline RawCvSink::RawCvSink(std::string_view 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);
+ cv::Mat tmpnam;
+ auto retVal = GrabFrameDirect(tmpnam);
if (retVal <= 0) {
return retVal;
}
- tmpMat.copyTo(image);
+ tmpnam.copyTo(image);
return retVal;
}
inline uint64_t RawCvSink::GrabFrameNoTimeout(cv::Mat& image) {
- cv::Mat tmpMat;
- auto retVal = GrabFrameNoTimeoutDirect(tmpMat);
+ cv::Mat tmpnam;
+ auto retVal = GrabFrameNoTimeoutDirect(tmpnam);
if (retVal <= 0) {
return retVal;
}
- tmpMat.copyTo(image);
+ tmpnam.copyTo(image);
return retVal;
}
@@ -198,7 +198,9 @@
rawFrame.width = 0;
rawFrame.pixelFormat = CS_PixelFormat::CS_PIXFMT_BGR;
m_status = RawSink::GrabFrame(rawFrame, timeout);
- if (m_status <= 0) return m_status;
+ if (m_status <= 0) {
+ return m_status;
+ }
image = cv::Mat{rawFrame.height, rawFrame.width, CV_8UC3, rawFrame.data};
return m_status;
}
@@ -208,7 +210,9 @@
rawFrame.width = 0;
rawFrame.pixelFormat = CS_PixelFormat::CS_PIXFMT_BGR;
m_status = RawSink::GrabFrameNoTimeout(rawFrame);
- if (m_status <= 0) return m_status;
+ if (m_status <= 0) {
+ return m_status;
+ }
image = cv::Mat{rawFrame.height, rawFrame.width, CV_8UC3, rawFrame.data};
return m_status;
}
diff --git a/cscore/src/main/native/linux/NetworkListener.cpp b/cscore/src/main/native/linux/NetworkListener.cpp
index 6915b30..1a0ac8b 100644
--- a/cscore/src/main/native/linux/NetworkListener.cpp
+++ b/cscore/src/main/native/linux/NetworkListener.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#include "NetworkListener.h"
@@ -37,7 +34,7 @@
public:
Thread(wpi::Logger& logger, Notifier& notifier)
: m_logger(logger), m_notifier(notifier) {}
- void Main();
+ void Main() override;
wpi::Logger& m_logger;
Notifier& m_notifier;
@@ -50,7 +47,9 @@
NetworkListener::NetworkListener(wpi::Logger& logger, Notifier& notifier)
: m_impl(std::make_unique<Impl>(logger, notifier)) {}
-NetworkListener::~NetworkListener() { Stop(); }
+NetworkListener::~NetworkListener() {
+ Stop();
+}
void NetworkListener::Start() {
m_impl->m_owner.Start(m_impl->m_logger, m_impl->m_notifier);
@@ -60,7 +59,9 @@
// Wake up thread
if (auto thr = m_impl->m_owner.GetThread()) {
thr->m_active = false;
- if (thr->m_command_fd >= 0) eventfd_write(thr->m_command_fd, 1);
+ if (thr->m_command_fd >= 0) {
+ eventfd_write(thr->m_command_fd, 1);
+ }
}
m_impl->m_owner.Stop();
}
@@ -69,15 +70,15 @@
// Create event socket so we can be shut down
m_command_fd = ::eventfd(0, 0);
if (m_command_fd < 0) {
- ERROR(
- "NetworkListener: could not create eventfd: " << std::strerror(errno));
+ ERROR("NetworkListener: could not create eventfd: {}",
+ std::strerror(errno));
return;
}
// Create netlink socket
int sd = ::socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if (sd < 0) {
- ERROR("NetworkListener: could not create socket: " << std::strerror(errno));
+ ERROR("NetworkListener: could not create socket: {}", std::strerror(errno));
::close(m_command_fd);
m_command_fd = -1;
return;
@@ -89,7 +90,7 @@
addr.nl_family = AF_NETLINK;
addr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR;
if (bind(sd, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)) < 0) {
- ERROR("NetworkListener: could not create socket: " << std::strerror(errno));
+ ERROR("NetworkListener: could not create socket: {}", std::strerror(errno));
::close(sd);
::close(m_command_fd);
m_command_fd = -1;
@@ -112,30 +113,40 @@
int nfds = std::max(m_command_fd, sd) + 1;
if (::select(nfds, &readfds, nullptr, nullptr, &tv) < 0) {
- ERROR("NetworkListener: select(): " << std::strerror(errno));
+ ERROR("NetworkListener: select(): {}", std::strerror(errno));
break; // XXX: is this the right thing to do here?
}
// Double-check to see if we're shutting down
- if (!m_active) break;
+ if (!m_active) {
+ break;
+ }
- if (!FD_ISSET(sd, &readfds)) continue;
+ if (!FD_ISSET(sd, &readfds)) {
+ continue;
+ }
std::memset(&addr, 0, sizeof(addr));
struct iovec iov = {buf, sizeof(buf)};
struct msghdr msg = {&addr, sizeof(addr), &iov, 1, nullptr, 0, 0};
int len = ::recvmsg(sd, &msg, 0);
if (len < 0) {
- if (errno == EWOULDBLOCK || errno == EAGAIN) continue;
- ERROR(
- "NetworkListener: could not read netlink: " << std::strerror(errno));
+ if (errno == EWOULDBLOCK || errno == EAGAIN) {
+ continue;
+ }
+ ERROR("NetworkListener: could not read netlink: {}",
+ std::strerror(errno));
break; // XXX: is this the right thing to do here?
}
- if (len == 0) continue; // EOF?
+ 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, ulen); nh = NLMSG_NEXT(nh, ulen)) {
- if (nh->nlmsg_type == NLMSG_DONE) break;
+ 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) {
m_notifier.NotifyNetworkInterfacesChanged();
diff --git a/cscore/src/main/native/linux/NetworkUtil.cpp b/cscore/src/main/native/linux/NetworkUtil.cpp
index 2c1f3cd..43e0fa8 100644
--- a/cscore/src/main/native/linux/NetworkUtil.cpp
+++ b/cscore/src/main/native/linux/NetworkUtil.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2018 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#include "cscore_cpp.h" // NOLINT(build/include_order)
@@ -16,17 +13,25 @@
std::vector<std::string> GetNetworkInterfaces() {
struct ifaddrs* ifa;
- if (::getifaddrs(&ifa) != 0) return std::vector<std::string>{};
+ if (::getifaddrs(&ifa) != 0) {
+ return {};
+ }
std::vector<std::string> rv;
char buf[256];
for (struct ifaddrs* i = ifa; i; i = i->ifa_next) {
- if (!i->ifa_addr) continue; // no address
- if (i->ifa_addr->sa_family != AF_INET) continue; // only return IPv4
+ if (!i->ifa_addr) {
+ continue; // no address
+ }
+ if (i->ifa_addr->sa_family != AF_INET) {
+ continue; // only return IPv4
+ }
struct sockaddr_in* addr_in = reinterpret_cast<sockaddr_in*>(i->ifa_addr);
const char* addr =
::inet_ntop(addr_in->sin_family, &addr_in->sin_addr, buf, sizeof(buf));
- if (!addr) continue; // error converting address
+ if (!addr) {
+ continue; // error converting address
+ }
rv.emplace_back(addr);
}
diff --git a/cscore/src/main/native/linux/UsbCameraBuffer.h b/cscore/src/main/native/linux/UsbCameraBuffer.h
index 98ac149..91fd588 100644
--- a/cscore/src/main/native/linux/UsbCameraBuffer.h
+++ b/cscore/src/main/native/linux/UsbCameraBuffer.h
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2018 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#ifndef CSCORE_USBCAMERABUFFER_H_
#define CSCORE_USBCAMERABUFFER_H_
@@ -16,7 +13,7 @@
class UsbCameraBuffer {
public:
- UsbCameraBuffer() noexcept : m_data{nullptr}, m_length{0} {}
+ UsbCameraBuffer() noexcept = default;
UsbCameraBuffer(UsbCameraBuffer&& other) noexcept : UsbCameraBuffer() {
swap(*this, other);
}
@@ -38,7 +35,9 @@
}
~UsbCameraBuffer() {
- if (m_data) munmap(m_data, m_length);
+ if (m_data) {
+ munmap(m_data, m_length);
+ }
}
friend void swap(UsbCameraBuffer& first, UsbCameraBuffer& second) noexcept {
@@ -47,8 +46,8 @@
swap(first.m_length, second.m_length);
}
- void* m_data;
- size_t m_length;
+ void* m_data{nullptr};
+ size_t m_length{0};
};
} // namespace cs
diff --git a/cscore/src/main/native/linux/UsbCameraImpl.cpp b/cscore/src/main/native/linux/UsbCameraImpl.cpp
index 1175ca3..a08fbbc 100644
--- a/cscore/src/main/native/linux/UsbCameraImpl.cpp
+++ b/cscore/src/main/native/linux/UsbCameraImpl.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2020 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#include "UsbCameraImpl.h"
@@ -23,11 +20,13 @@
#include <unistd.h>
#include <algorithm>
+#include <memory>
-#include <wpi/FileSystem.h>
+#include <fmt/format.h>
#include <wpi/MemAlloc.h>
-#include <wpi/Path.h>
#include <wpi/SmallString.h>
+#include <wpi/StringExtras.h>
+#include <wpi/fs.h>
#include <wpi/raw_ostream.h>
#include <wpi/timestamp.h>
@@ -42,6 +41,14 @@
using namespace cs;
+namespace {
+// Find the length of an array.
+template <class T, size_t N>
+constexpr inline size_t array_lengthof(T (&)[N]) {
+ return N;
+}
+} // namespace
+
static constexpr char const* kPropWbAuto = "white_balance_temperature_auto";
static constexpr char const* kPropWbValue = "white_balance_temperature";
static constexpr char const* kPropExAuto = "exposure_auto";
@@ -98,8 +105,10 @@
}
}
-static bool IsPercentageProperty(wpi::StringRef name) {
- if (name.startswith("raw_")) name = name.substr(4);
+static bool IsPercentageProperty(std::string_view name) {
+ if (wpi::starts_with(name, "raw_")) {
+ name = name.substr(4);
+ }
return name == "brightness" || name == "contrast" || name == "saturation" ||
name == "hue" || name == "sharpness" || name == "gain" ||
name == "exposure_absolute" || name == "exposure_time_absolute";
@@ -123,9 +132,11 @@
// LifeCam exposure setting quirk
if (m_lifecam_exposure && rawProp.name == "raw_exposure_absolute" &&
rawProp.minimum == 5 && rawProp.maximum == 20000) {
- int nelems = wpi::array_lengthof(quirkLifeCamHd3000);
+ int nelems = array_lengthof(quirkLifeCamHd3000);
for (int i = 0; i < nelems; ++i) {
- if (rawValue < quirkLifeCamHd3000[i]) return 100.0 * i / nelems;
+ if (rawValue < quirkLifeCamHd3000[i]) {
+ return 100.0 * i / nelems;
+ }
}
return 100;
}
@@ -138,10 +149,14 @@
// LifeCam exposure setting quirk
if (m_lifecam_exposure && rawProp.name == "raw_exposure_absolute" &&
rawProp.minimum == 5 && rawProp.maximum == 20000) {
- int nelems = wpi::array_lengthof(quirkLifeCamHd3000);
+ int nelems = array_lengthof(quirkLifeCamHd3000);
int ndx = nelems * percentValue / 100.0;
- if (ndx < 0) ndx = 0;
- if (ndx >= nelems) ndx = nelems - 1;
+ if (ndx < 0) {
+ ndx = 0;
+ }
+ if (ndx >= nelems) {
+ ndx = nelems - 1;
+ }
return quirkLifeCamHd3000[ndx];
}
return rawProp.minimum +
@@ -149,52 +164,64 @@
}
static bool GetVendorProduct(int dev, int* vendor, int* product) {
- wpi::SmallString<64> ifpath;
- {
- wpi::raw_svector_ostream oss{ifpath};
- oss << "/sys/class/video4linux/video" << dev << "/device/modalias";
- }
+ auto ifpath =
+ fmt::format("/sys/class/video4linux/video{}/device/modalias", dev);
int fd = open(ifpath.c_str(), O_RDONLY);
- if (fd < 0) return false;
+ if (fd < 0) {
+ return false;
+ }
char readBuf[128];
ssize_t n = read(fd, readBuf, sizeof(readBuf));
close(fd);
- if (n <= 0) return false;
- wpi::StringRef readStr{readBuf};
- if (readStr.substr(readStr.find('v')).substr(1, 4).getAsInteger(16, *vendor))
+ if (n <= 0) {
return false;
- if (readStr.substr(readStr.find('p')).substr(1, 4).getAsInteger(16, *product))
+ }
+ std::string_view readStr{readBuf};
+ if (auto v = wpi::parse_integer<int>(
+ readStr.substr(readStr.find('v')).substr(1, 4), 16)) {
+ *vendor = v.value();
+ } else {
return false;
+ }
+ if (auto v = wpi::parse_integer<int>(
+ readStr.substr(readStr.find('p')).substr(1, 4), 16)) {
+ *product = v.value();
+ } else {
+ return false;
+ }
return true;
}
static bool GetDescriptionSysV4L(int dev, std::string* desc) {
- wpi::SmallString<64> ifpath;
- {
- wpi::raw_svector_ostream oss{ifpath};
- oss << "/sys/class/video4linux/video" << dev << "/device/interface";
- }
+ auto ifpath =
+ fmt::format("/sys/class/video4linux/video{}/device/interface", dev);
int fd = open(ifpath.c_str(), O_RDONLY);
- if (fd < 0) return false;
+ if (fd < 0) {
+ return false;
+ }
char readBuf[128];
ssize_t n = read(fd, readBuf, sizeof(readBuf));
close(fd);
- if (n <= 0) return false;
+ if (n <= 0) {
+ return false;
+ }
- *desc = wpi::StringRef(readBuf, n).rtrim();
+ *desc = wpi::rtrim(std::string_view(readBuf, n));
return true;
}
static bool GetDescriptionIoctl(const char* cpath, std::string* desc) {
int fd = open(cpath, O_RDWR);
- if (fd < 0) return false;
+ if (fd < 0) {
+ return false;
+ }
struct v4l2_capability vcap;
std::memset(&vcap, 0, sizeof(vcap));
@@ -204,17 +231,16 @@
}
close(fd);
- wpi::StringRef card{reinterpret_cast<const char*>(vcap.card)};
+ std::string_view card{reinterpret_cast<const char*>(vcap.card)};
// try to convert "UVC Camera (0000:0000)" into a better name
- int vendor = 0;
- int product = 0;
- if (card.startswith("UVC Camera (") &&
- !card.substr(12, 4).getAsInteger(16, vendor) &&
- !card.substr(17, 4).getAsInteger(16, product)) {
- wpi::SmallString<64> card2Buf;
- wpi::StringRef card2 = GetUsbNameFromId(vendor, product, card2Buf);
+ std::optional<int> vendor;
+ std::optional<int> product;
+ if (wpi::starts_with(card, "UVC Camera (") &&
+ (vendor = wpi::parse_integer<int>(card.substr(12, 4), 16)) &&
+ (product = wpi::parse_integer<int>(card.substr(17, 4), 16))) {
+ std::string card2 = GetUsbNameFromId(vendor.value(), product.value());
if (!card2.empty()) {
- *desc = card2;
+ *desc = std::move(card2);
return true;
}
}
@@ -225,7 +251,9 @@
static bool IsVideoCaptureDevice(const char* cpath) {
int fd = open(cpath, O_RDWR);
- if (fd < 0) return false;
+ if (fd < 0) {
+ return false;
+ }
struct v4l2_capability vcap;
std::memset(&vcap, 0, sizeof(vcap));
@@ -243,25 +271,22 @@
}
static int GetDeviceNum(const char* cpath) {
- wpi::StringRef path{cpath};
- std::string pathBuf;
+ fs::path path{cpath};
// it might be a symlink; if so, find the symlink target (e.g. /dev/videoN),
// add that to the list and make it the keypath
- if (wpi::sys::fs::is_symlink_file(cpath)) {
- char* target = ::realpath(cpath, nullptr);
- if (target) {
- pathBuf = target;
- path = pathBuf;
- std::free(target);
- }
+ if (fs::is_symlink(path)) {
+ path = fs::canonical(path);
}
- path = wpi::sys::path::filename(path);
- if (!path.startswith("video")) return -1;
- int dev = -1;
- if (path.substr(5).getAsInteger(10, dev)) return -1;
- return dev;
+ std::string fn = path.filename();
+ if (!wpi::starts_with(fn, "video")) {
+ return -1;
+ }
+ if (auto dev = wpi::parse_integer<int>(fn.substr(5), 10)) {
+ return dev.value();
+ }
+ return -1;
}
static std::string GetDescriptionImpl(const char* cpath) {
@@ -270,23 +295,27 @@
int dev = GetDeviceNum(cpath);
if (dev >= 0) {
// Sometimes the /sys tree gives a better name.
- if (GetDescriptionSysV4L(dev, &rv)) return rv;
+ if (GetDescriptionSysV4L(dev, &rv)) {
+ return rv;
+ }
}
// Otherwise use an ioctl to query the caps and get the card name
- if (GetDescriptionIoctl(cpath, &rv)) return rv;
+ if (GetDescriptionIoctl(cpath, &rv)) {
+ return rv;
+ }
return std::string{};
}
-UsbCameraImpl::UsbCameraImpl(const wpi::Twine& name, wpi::Logger& logger,
+UsbCameraImpl::UsbCameraImpl(std::string_view name, wpi::Logger& logger,
Notifier& notifier, Telemetry& telemetry,
- const wpi::Twine& path)
+ std::string_view path)
: SourceImpl{name, logger, notifier, telemetry},
m_fd{-1},
m_command_fd{eventfd(0, 0)},
m_active{true},
- m_path{path.str()} {
+ m_path{path} {
SetDescription(GetDescriptionImpl(m_path.c_str()));
SetQuirks();
@@ -308,17 +337,23 @@
Send(Message{Message::kNone});
// join camera thread
- if (m_cameraThread.joinable()) m_cameraThread.join();
+ if (m_cameraThread.joinable()) {
+ m_cameraThread.join();
+ }
// close command fd
int fd = m_command_fd.exchange(-1);
- if (fd >= 0) close(fd);
+ if (fd >= 0) {
+ close(fd);
+ }
}
static inline void DoFdSet(int fd, fd_set* set, int* nfds) {
if (fd >= 0) {
FD_SET(fd, set);
- if ((fd + 1) > *nfds) *nfds = fd + 1;
+ if ((fd + 1) > *nfds) {
+ *nfds = fd + 1;
+ }
}
}
@@ -341,8 +376,8 @@
close(notify_fd);
notify_fd = -1;
} else {
- notify_is.reset(new wpi::raw_fd_istream{
- notify_fd, true, sizeof(struct inotify_event) + NAME_MAX + 1});
+ notify_is = std::make_unique<wpi::raw_fd_istream>(
+ notify_fd, true, sizeof(struct inotify_event) + NAME_MAX + 1);
}
}
bool notified = (notify_fd < 0); // treat as always notified if cannot notify
@@ -360,12 +395,16 @@
while (m_active) {
// If not connected, try to reconnect
- if (m_fd < 0) DeviceConnect();
+ if (m_fd < 0) {
+ DeviceConnect();
+ }
// Make copies of fd's in case they go away
int command_fd = m_command_fd.load();
int fd = m_fd.load();
- if (!m_active) break;
+ if (!m_active) {
+ break;
+ }
// Reset notified flag and restart streaming if necessary
if (fd >= 0) {
@@ -398,20 +437,24 @@
fd_set readfds;
FD_ZERO(&readfds);
DoFdSet(command_fd, &readfds, &nfds);
- if (m_streaming) DoFdSet(fd, &readfds, &nfds);
+ if (m_streaming) {
+ DoFdSet(fd, &readfds, &nfds);
+ }
DoFdSet(notify_fd, &readfds, &nfds);
if (select(nfds, &readfds, nullptr, nullptr, &tv) < 0) {
- SERROR("select(): " << std::strerror(errno));
+ SERROR("select(): {}", std::strerror(errno));
break; // XXX: is this the right thing to do here?
}
// Double-check to see if we're shutting down
- if (!m_active) break;
+ if (!m_active) {
+ break;
+ }
// Handle notify events
if (notify_fd >= 0 && FD_ISSET(notify_fd, &readfds)) {
- SDEBUG4("notify event");
+ SDEBUG4("{}", "notify event");
struct inotify_event event;
do {
// Read the event structure
@@ -421,10 +464,9 @@
raw_name.resize(event.len);
notify_is->read(raw_name.data(), event.len);
// If the name is what we expect...
- wpi::StringRef name{raw_name.c_str()};
- SDEBUG4("got event on '" << name << "' (" << name.size()
- << ") compare to '" << base << "' ("
- << base.size() << ") mask " << event.mask);
+ std::string_view name{raw_name.c_str()};
+ SDEBUG4("got event on '{}' ({}) compare to '{}' ({}) mask {}", name,
+ name.size(), base, base.size(), event.mask);
if (name == base) {
if ((event.mask & IN_DELETE) != 0) {
wasStreaming = m_streaming;
@@ -441,7 +483,7 @@
// Handle commands
if (command_fd >= 0 && FD_ISSET(command_fd, &readfds)) {
- SDEBUG4("got command");
+ SDEBUG4("{}", "got command");
// Read it to clear
eventfd_t val;
eventfd_read(command_fd, &val);
@@ -451,7 +493,7 @@
// Handle frames
if (m_streaming && fd >= 0 && FD_ISSET(fd, &readfds)) {
- SDEBUG4("grabbing image");
+ SDEBUG4("{}", "grabbing image");
// Dequeue buffer
struct v4l2_buffer buf;
@@ -459,7 +501,7 @@
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
if (DoIoctl(fd, VIDIOC_DQBUF, &buf) != 0) {
- SWARNING("could not dequeue buffer");
+ SWARNING("{}", "could not dequeue buffer");
wasStreaming = m_streaming;
DeviceStreamOff();
DeviceDisconnect();
@@ -468,14 +510,14 @@
}
if ((buf.flags & V4L2_BUF_FLAG_ERROR) == 0) {
- SDEBUG4("got image size=" << buf.bytesused << " index=" << buf.index);
+ SDEBUG4("got image size={} index={}", buf.bytesused, buf.index);
if (buf.index >= kNumBuffers || !m_buffers[buf.index].m_data) {
- SWARNING("invalid buffer" << buf.index);
+ SWARNING("invalid buffer {}", buf.index);
continue;
}
- wpi::StringRef image{
+ std::string_view image{
static_cast<const char*>(m_buffers[buf.index].m_data),
static_cast<size_t>(buf.bytesused)};
int width = m_mode.width;
@@ -483,7 +525,7 @@
bool good = true;
if (m_mode.pixelFormat == VideoMode::kMJPEG &&
!GetJpegSize(image, &width, &height)) {
- SWARNING("invalid JPEG image received from camera");
+ SWARNING("{}", "invalid JPEG image received from camera");
good = false;
}
if (good) {
@@ -494,7 +536,7 @@
// Requeue buffer
if (DoIoctl(fd, VIDIOC_QBUF, &buf) != 0) {
- SWARNING("could not requeue buffer");
+ SWARNING("{}", "could not requeue buffer");
wasStreaming = m_streaming;
DeviceStreamOff();
DeviceDisconnect();
@@ -511,10 +553,14 @@
void UsbCameraImpl::DeviceDisconnect() {
int fd = m_fd.exchange(-1);
- if (fd < 0) return; // already disconnected
+ if (fd < 0) {
+ return; // already disconnected
+ }
// Unmap buffers
- for (int i = 0; i < kNumBuffers; ++i) m_buffers[i] = UsbCameraBuffer{};
+ for (int i = 0; i < kNumBuffers; ++i) {
+ m_buffers[i] = UsbCameraBuffer{};
+ }
// Close device
close(fd);
@@ -524,67 +570,76 @@
}
void UsbCameraImpl::DeviceConnect() {
- if (m_fd >= 0) return;
+ if (m_fd >= 0) {
+ return;
+ }
- if (m_connectVerbose) SINFO("Connecting to USB camera on " << m_path);
+ if (m_connectVerbose) {
+ SINFO("Connecting to USB camera on {}", m_path);
+ }
// Try to open the device
- SDEBUG3("opening device");
+ SDEBUG3("{}", "opening device");
int fd = open(m_path.c_str(), O_RDWR);
- if (fd < 0) return;
+ if (fd < 0) {
+ return;
+ }
m_fd = fd;
// Get capabilities
- SDEBUG3("getting capabilities");
+ SDEBUG3("{}", "getting capabilities");
struct v4l2_capability vcap;
std::memset(&vcap, 0, sizeof(vcap));
if (DoIoctl(fd, VIDIOC_QUERYCAP, &vcap) >= 0) {
m_capabilities = vcap.capabilities;
- if (m_capabilities & V4L2_CAP_DEVICE_CAPS)
+ if (m_capabilities & V4L2_CAP_DEVICE_CAPS) {
m_capabilities = vcap.device_caps;
+ }
}
// Get or restore video mode
if (!m_properties_cached) {
- SDEBUG3("caching properties");
+ SDEBUG3("{}", "caching properties");
DeviceCacheProperties();
DeviceCacheVideoModes();
DeviceCacheMode();
m_properties_cached = true;
} else {
- SDEBUG3("restoring video mode");
+ SDEBUG3("{}", "restoring video mode");
DeviceSetMode();
DeviceSetFPS();
// Restore settings
- SDEBUG3("restoring settings");
+ SDEBUG3("{}", "restoring settings");
std::unique_lock lock2(m_mutex);
for (size_t i = 0; i < m_propertyData.size(); ++i) {
const auto prop =
static_cast<const UsbCameraProperty*>(m_propertyData[i].get());
- if (!prop || !prop->valueSet || !prop->device || prop->percentage)
+ if (!prop || !prop->valueSet || !prop->device || prop->percentage) {
continue;
- if (!prop->DeviceSet(lock2, m_fd))
- SWARNING("failed to set property " << prop->name);
+ }
+ if (!prop->DeviceSet(lock2, m_fd)) {
+ SWARNING("failed to set property {}", prop->name);
+ }
}
}
// Request buffers
- SDEBUG3("allocating buffers");
+ SDEBUG3("{}", "allocating buffers");
struct v4l2_requestbuffers rb;
std::memset(&rb, 0, sizeof(rb));
rb.count = kNumBuffers;
rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
rb.memory = V4L2_MEMORY_MMAP;
if (DoIoctl(fd, VIDIOC_REQBUFS, &rb) != 0) {
- SWARNING("could not allocate buffers");
+ SWARNING("{}", "could not allocate buffers");
close(fd);
m_fd = -1;
return;
}
// Map buffers
- SDEBUG3("mapping buffers");
+ SDEBUG3("{}", "mapping buffers");
for (int i = 0; i < kNumBuffers; ++i) {
struct v4l2_buffer buf;
std::memset(&buf, 0, sizeof(buf));
@@ -592,25 +647,26 @@
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
if (DoIoctl(fd, VIDIOC_QUERYBUF, &buf) != 0) {
- SWARNING("could not query buffer " << i);
+ SWARNING("could not query buffer {}", i);
close(fd);
m_fd = -1;
return;
}
- SDEBUG4("buf " << i << " length=" << buf.length
- << " offset=" << buf.m.offset);
+ SDEBUG4("buf {} length={} offset={}", i, buf.length, buf.m.offset);
m_buffers[i] = UsbCameraBuffer(fd, buf.length, buf.m.offset);
if (!m_buffers[i].m_data) {
- SWARNING("could not map buffer " << i);
+ SWARNING("could not map buffer {}", i);
// release other buffers
- for (int j = 0; j < i; ++j) m_buffers[j] = UsbCameraBuffer{};
+ for (int j = 0; j < i; ++j) {
+ m_buffers[j] = UsbCameraBuffer{};
+ }
close(fd);
m_fd = -1;
return;
}
- SDEBUG4("buf " << i << " address=" << m_buffers[i].m_data);
+ SDEBUG4("buf {} address={}", i, m_buffers[i].m_data);
}
// Update description (as it may have changed)
@@ -624,12 +680,16 @@
}
bool UsbCameraImpl::DeviceStreamOn() {
- if (m_streaming) return false; // ignore if already enabled
+ if (m_streaming) {
+ return false; // ignore if already enabled
+ }
int fd = m_fd.load();
- if (fd < 0) return false;
+ if (fd < 0) {
+ return false;
+ }
// Queue buffers
- SDEBUG3("queuing buffers");
+ SDEBUG3("{}", "queuing buffers");
for (int i = 0; i < kNumBuffers; ++i) {
struct v4l2_buffer buf;
std::memset(&buf, 0, sizeof(buf));
@@ -637,7 +697,7 @@
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
if (DoIoctl(fd, VIDIOC_QBUF, &buf) != 0) {
- SWARNING("could not queue buffer " << i);
+ SWARNING("could not queue buffer {}", i);
return false;
}
}
@@ -648,27 +708,34 @@
if (errno == ENOSPC) {
// indicates too much USB bandwidth requested
SERROR(
+ "{}",
"could not start streaming due to USB bandwidth limitations; try a "
"lower resolution or a different pixel format (VIDIOC_STREAMON: "
"No space left on device)");
} else {
// some other error
- SERROR("ioctl VIDIOC_STREAMON failed: " << std::strerror(errno));
+ SERROR("ioctl VIDIOC_STREAMON failed: {}", std::strerror(errno));
}
return false;
}
- SDEBUG4("enabled streaming");
+ SDEBUG4("{}", "enabled streaming");
m_streaming = true;
return true;
}
bool UsbCameraImpl::DeviceStreamOff() {
- if (!m_streaming) return false; // ignore if already disabled
+ if (!m_streaming) {
+ return false; // ignore if already disabled
+ }
int fd = m_fd.load();
- if (fd < 0) return false;
+ if (fd < 0) {
+ return false;
+ }
int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- if (DoIoctl(fd, VIDIOC_STREAMOFF, &type) != 0) return false;
- SDEBUG4("disabled streaming");
+ if (DoIoctl(fd, VIDIOC_STREAMOFF, &type) != 0) {
+ return false;
+ }
+ SDEBUG4("{}", "disabled streaming");
m_streaming = false;
return true;
}
@@ -706,12 +773,16 @@
m_mode = newMode;
lock.unlock();
bool wasStreaming = m_streaming;
- if (wasStreaming) DeviceStreamOff();
+ if (wasStreaming) {
+ DeviceStreamOff();
+ }
if (m_fd >= 0) {
DeviceDisconnect();
DeviceConnect();
}
- if (wasStreaming) DeviceStreamOn();
+ if (wasStreaming) {
+ DeviceStreamOn();
+ }
m_notifier.NotifySourceVideoMode(*this, newMode);
lock.lock();
} else if (newMode.fps != m_mode.fps) {
@@ -719,9 +790,13 @@
lock.unlock();
// Need to stop streaming to set FPS
bool wasStreaming = m_streaming;
- if (wasStreaming) DeviceStreamOff();
+ if (wasStreaming) {
+ DeviceStreamOff();
+ }
DeviceSetFPS();
- if (wasStreaming) DeviceStreamOn();
+ if (wasStreaming) {
+ DeviceStreamOn();
+ }
m_notifier.NotifySourceVideoMode(*this, newMode);
lock.lock();
}
@@ -734,25 +809,29 @@
bool setString = (msg.kind == Message::kCmdSetPropertyStr);
int property = msg.data[0];
int value = msg.data[1];
- wpi::StringRef valueStr = msg.dataStr;
+ std::string_view valueStr = msg.dataStr;
// Look up
auto prop = static_cast<UsbCameraProperty*>(GetProperty(property));
- if (!prop) return CS_INVALID_PROPERTY;
+ if (!prop) {
+ return CS_INVALID_PROPERTY;
+ }
// If setting before we get, guess initial type based on set
if (prop->propKind == CS_PROP_NONE) {
- if (setString)
+ if (setString) {
prop->propKind = CS_PROP_STRING;
- else
+ } else {
prop->propKind = CS_PROP_INTEGER;
+ }
}
// Check kind match
if ((setString && prop->propKind != CS_PROP_STRING) ||
- (!setString && (prop->propKind &
- (CS_PROP_BOOLEAN | CS_PROP_INTEGER | CS_PROP_ENUM)) == 0))
+ (!setString && (prop->propKind & (CS_PROP_BOOLEAN | CS_PROP_INTEGER |
+ CS_PROP_ENUM)) == 0)) {
return CS_WRONG_PROPERTY_TYPE;
+ }
// Handle percentage property
int percentageProperty = prop->propPair;
@@ -769,17 +848,21 @@
// Actually set the new value on the device (if possible)
if (!prop->device) {
- if (prop->id == kPropConnectVerboseId) m_connectVerbose = value;
+ if (prop->id == kPropConnectVerboseId) {
+ m_connectVerbose = value;
+ }
} else {
- if (!prop->DeviceSet(lock, m_fd, value, valueStr))
+ if (!prop->DeviceSet(lock, m_fd, value, valueStr)) {
return CS_PROPERTY_WRITE_FAILED;
+ }
}
// Cache the set values
UpdatePropertyValue(property, setString, value, valueStr);
- if (percentageProperty != 0)
+ if (percentageProperty != 0) {
UpdatePropertyValue(percentageProperty, setString, percentageValue,
valueStr);
+ }
return CS_OK;
}
@@ -790,12 +873,16 @@
lock.unlock();
// disconnect and reconnect
bool wasStreaming = m_streaming;
- if (wasStreaming) DeviceStreamOff();
+ if (wasStreaming) {
+ DeviceStreamOff();
+ }
if (m_fd >= 0) {
DeviceDisconnect();
DeviceConnect();
}
- if (wasStreaming) DeviceStreamOn();
+ if (wasStreaming) {
+ DeviceStreamOn();
+ }
lock.lock();
return CS_OK;
}
@@ -822,15 +909,18 @@
void UsbCameraImpl::DeviceProcessCommands() {
std::unique_lock lock(m_mutex);
- if (m_commands.empty()) return;
+ if (m_commands.empty()) {
+ return;
+ }
while (!m_commands.empty()) {
auto msg = std::move(m_commands.back());
m_commands.pop_back();
CS_StatusValue status = DeviceProcessCommand(lock, msg);
if (msg.kind != Message::kNumSinksChanged &&
- msg.kind != Message::kNumSinksEnabledChanged)
+ msg.kind != Message::kNumSinksEnabledChanged) {
m_responses.emplace_back(msg.from, status);
+ }
}
lock.unlock();
m_responseCv.notify_all();
@@ -838,7 +928,9 @@
void UsbCameraImpl::DeviceSetMode() {
int fd = m_fd.load();
- if (fd < 0) return;
+ if (fd < 0) {
+ return;
+ }
struct v4l2_format vfmt;
std::memset(&vfmt, 0, sizeof(vfmt));
@@ -851,43 +943,52 @@
vfmt.fmt.pix.pixelformat =
FromPixelFormat(static_cast<VideoMode::PixelFormat>(m_mode.pixelFormat));
if (vfmt.fmt.pix.pixelformat == 0) {
- SWARNING("could not set format " << m_mode.pixelFormat
- << ", defaulting to MJPEG");
+ SWARNING("could not set format {}, defaulting to MJPEG",
+ m_mode.pixelFormat);
vfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
}
vfmt.fmt.pix.width = m_mode.width;
vfmt.fmt.pix.height = m_mode.height;
vfmt.fmt.pix.field = V4L2_FIELD_ANY;
if (DoIoctl(fd, VIDIOC_S_FMT, &vfmt) != 0) {
- SWARNING("could not set format " << m_mode.pixelFormat << " res "
- << m_mode.width << "x" << m_mode.height);
+ SWARNING("could not set format {} res {}x{}", m_mode.pixelFormat,
+ m_mode.width, m_mode.height);
} else {
- SINFO("set format " << m_mode.pixelFormat << " res " << m_mode.width << "x"
- << m_mode.height);
+ SINFO("set format {} res {}x{}", m_mode.pixelFormat, m_mode.width,
+ m_mode.height);
}
}
void UsbCameraImpl::DeviceSetFPS() {
int fd = m_fd.load();
- if (fd < 0) return;
+ if (fd < 0) {
+ return;
+ }
struct v4l2_streamparm parm;
std::memset(&parm, 0, sizeof(parm));
parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- if (DoIoctl(fd, VIDIOC_G_PARM, &parm) != 0) return;
- if ((parm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) == 0) return;
+ if (DoIoctl(fd, VIDIOC_G_PARM, &parm) != 0) {
+ return;
+ }
+ if ((parm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) == 0) {
+ return;
+ }
std::memset(&parm, 0, sizeof(parm));
parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
parm.parm.capture.timeperframe = FPSToFract(m_mode.fps);
- if (DoIoctl(fd, VIDIOC_S_PARM, &parm) != 0)
- SWARNING("could not set FPS to " << m_mode.fps);
- else
- SINFO("set FPS to " << m_mode.fps);
+ if (DoIoctl(fd, VIDIOC_S_PARM, &parm) != 0) {
+ SWARNING("could not set FPS to {}", m_mode.fps);
+ } else {
+ SINFO("set FPS to {}", m_mode.fps);
+ }
}
void UsbCameraImpl::DeviceCacheMode() {
int fd = m_fd.load();
- if (fd < 0) return;
+ if (fd < 0) {
+ return;
+ }
// Get format
struct v4l2_format vfmt;
@@ -899,7 +1000,7 @@
#endif
vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (DoIoctl(fd, VIDIOC_G_FMT, &vfmt) != 0) {
- SERROR("could not read current video mode");
+ SERROR("{}", "could not read current video mode");
std::scoped_lock lock(m_mutex);
m_mode = VideoMode{VideoMode::kMJPEG, 320, 240, 30};
return;
@@ -914,8 +1015,9 @@
std::memset(&parm, 0, sizeof(parm));
parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (TryIoctl(fd, VIDIOC_G_PARM, &parm) == 0) {
- if (parm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME)
+ if (parm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) {
fps = FractToFPS(parm.parm.capture.timeperframe);
+ }
}
// Update format with user changes.
@@ -946,7 +1048,9 @@
// Default to lowest known resolution (based on number of total pixels)
int numPixels = width * height;
for (const auto& mode : m_videoModes) {
- if (mode.pixelFormat != pixelFormat) continue;
+ if (mode.pixelFormat != pixelFormat) {
+ continue;
+ }
int numPixelsHere = mode.width * mode.height;
if (numPixelsHere < numPixels) {
formatChanged = true;
@@ -973,8 +1077,12 @@
m_mode.fps = fps;
}
- if (formatChanged) DeviceSetMode();
- if (fpsChanged) DeviceSetFPS();
+ if (formatChanged) {
+ DeviceSetMode();
+ }
+ if (fpsChanged) {
+ DeviceSetFPS();
+ }
m_notifier.NotifySourceVideoMode(*this, m_mode);
}
@@ -1027,8 +1135,9 @@
rawProp->valueStr = perProp->valueStr; // copy
} else {
// Read current raw value and set percentage from it
- if (!rawProp->DeviceGet(lock, m_fd))
- SWARNING("failed to get property " << rawProp->name);
+ if (!rawProp->DeviceGet(lock, m_fd)) {
+ SWARNING("failed to get property {}", rawProp->name);
+ }
if (perProp) {
perProp->SetValue(RawToPercentage(*rawProp, rawProp->value));
@@ -1038,8 +1147,9 @@
// Set value on device if user-configured
if (rawProp->valueSet) {
- if (!rawProp->DeviceSet(lock, m_fd))
- SWARNING("failed to set property " << rawProp->name);
+ if (!rawProp->DeviceSet(lock, m_fd)) {
+ SWARNING("failed to set property {}", rawProp->name);
+ }
}
// Update pointers since we released the lock
@@ -1079,12 +1189,16 @@
}
NotifyPropertyCreated(*rawIndex, *rawPropPtr);
- if (perPropPtr) NotifyPropertyCreated(*perIndex, *perPropPtr);
+ if (perPropPtr) {
+ NotifyPropertyCreated(*perIndex, *perPropPtr);
+ }
}
void UsbCameraImpl::DeviceCacheProperties() {
int fd = m_fd.load();
- if (fd < 0) return;
+ if (fd < 0) {
+ return;
+ }
#ifdef V4L2_CTRL_FLAG_NEXT_COMPOUND
constexpr __u32 nextFlags =
@@ -1102,20 +1216,24 @@
if (id == nextFlags) {
// try just enumerating standard...
for (id = V4L2_CID_BASE; id < V4L2_CID_LASTP1; ++id) {
- if (auto prop = UsbCameraProperty::DeviceQuery(fd, &id))
+ if (auto prop = UsbCameraProperty::DeviceQuery(fd, &id)) {
DeviceCacheProperty(std::move(prop));
+ }
}
// ... and custom controls
std::unique_ptr<UsbCameraProperty> prop;
for (id = V4L2_CID_PRIVATE_BASE;
- (prop = UsbCameraProperty::DeviceQuery(fd, &id)); ++id)
+ (prop = UsbCameraProperty::DeviceQuery(fd, &id)); ++id) {
DeviceCacheProperty(std::move(prop));
+ }
}
}
void UsbCameraImpl::DeviceCacheVideoModes() {
int fd = m_fd.load();
- if (fd < 0) return;
+ if (fd < 0) {
+ return;
+ }
std::vector<VideoMode> modes;
@@ -1125,7 +1243,9 @@
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
for (fmt.index = 0; TryIoctl(fd, VIDIOC_ENUM_FMT, &fmt) >= 0; ++fmt.index) {
VideoMode::PixelFormat pixelFormat = ToPixelFormat(fmt.pixelformat);
- if (pixelFormat == VideoMode::kUnknown) continue;
+ if (pixelFormat == VideoMode::kUnknown) {
+ continue;
+ }
// Frame sizes
struct v4l2_frmsizeenum frmsize;
@@ -1133,7 +1253,9 @@
frmsize.pixel_format = fmt.pixelformat;
for (frmsize.index = 0; TryIoctl(fd, VIDIOC_ENUM_FRAMESIZES, &frmsize) >= 0;
++frmsize.index) {
- if (frmsize.type != V4L2_FRMSIZE_TYPE_DISCRETE) continue;
+ if (frmsize.type != V4L2_FRMSIZE_TYPE_DISCRETE) {
+ continue;
+ }
// Frame intervals
struct v4l2_frmivalenum frmival;
@@ -1144,7 +1266,9 @@
for (frmival.index = 0;
TryIoctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &frmival) >= 0;
++frmival.index) {
- if (frmival.type != V4L2_FRMIVAL_TYPE_DISCRETE) continue;
+ if (frmival.type != V4L2_FRMIVAL_TYPE_DISCRETE) {
+ continue;
+ }
modes.emplace_back(pixelFormat,
static_cast<int>(frmsize.discrete.width),
@@ -1183,7 +1307,9 @@
CS_StatusValue UsbCameraImpl::SendAndWait(Message&& msg) const {
int fd = m_command_fd.load();
// exit early if not possible to signal
- if (fd < 0) return CS_SOURCE_IS_DISCONNECTED;
+ if (fd < 0) {
+ return CS_SOURCE_IS_DISCONNECTED;
+ }
auto from = msg.from;
@@ -1194,7 +1320,9 @@
}
// Signal the camera thread
- if (eventfd_write(fd, 1) < 0) return CS_SOURCE_IS_DISCONNECTED;
+ if (eventfd_write(fd, 1) < 0) {
+ return CS_SOURCE_IS_DISCONNECTED;
+ }
std::unique_lock lock(m_mutex);
while (m_active) {
@@ -1220,7 +1348,9 @@
void UsbCameraImpl::Send(Message&& msg) const {
int fd = m_command_fd.load();
// exit early if not possible to signal
- if (fd < 0) return;
+ if (fd < 0) {
+ return;
+ }
// Add the message to the command queue
{
@@ -1233,14 +1363,16 @@
}
std::unique_ptr<PropertyImpl> UsbCameraImpl::CreateEmptyProperty(
- const wpi::Twine& name) const {
+ std::string_view name) const {
return std::make_unique<UsbCameraProperty>(name);
}
bool UsbCameraImpl::CacheProperties(CS_Status* status) const {
// Wake up camera thread; this will try to reconnect
*status = SendAndWait(Message{Message::kNone});
- if (*status != CS_OK) return false;
+ if (*status != CS_OK) {
+ return false;
+ }
if (!m_properties_cached) {
*status = CS_SOURCE_IS_DISCONNECTED;
return false;
@@ -1250,10 +1382,10 @@
void UsbCameraImpl::SetQuirks() {
wpi::SmallString<128> descbuf;
- wpi::StringRef desc = GetDescription(descbuf);
- m_lifecam_exposure =
- desc.endswith("LifeCam HD-3000") || desc.endswith("LifeCam Cinema (TM)");
- m_picamera = desc.startswith("mmal service");
+ std::string_view desc = GetDescription(descbuf);
+ m_lifecam_exposure = wpi::ends_with(desc, "LifeCam HD-3000") ||
+ wpi::ends_with(desc, "LifeCam Cinema (TM)");
+ m_picamera = wpi::ends_with(desc, "mmal service");
int deviceNum = GetDeviceNum(m_path.c_str());
if (deviceNum >= 0) {
@@ -1271,11 +1403,11 @@
*status = SendAndWait(std::move(msg));
}
-void UsbCameraImpl::SetStringProperty(int property, const wpi::Twine& value,
+void UsbCameraImpl::SetStringProperty(int property, std::string_view value,
CS_Status* status) {
Message msg{Message::kCmdSetPropertyStr};
msg.data[0] = property;
- msg.dataStr = value.str();
+ msg.dataStr = value;
*status = SendAndWait(std::move(msg));
}
@@ -1395,9 +1527,9 @@
Send(Message{Message::kNumSinksEnabledChanged});
}
-void UsbCameraImpl::SetPath(const wpi::Twine& path, CS_Status* status) {
+void UsbCameraImpl::SetPath(std::string_view path, CS_Status* status) {
Message msg{Message::kCmdSetPath};
- msg.dataStr = path.str();
+ msg.dataStr = path;
*status = SendAndWait(std::move(msg));
}
@@ -1408,15 +1540,12 @@
namespace cs {
-CS_Source CreateUsbCameraDev(const wpi::Twine& name, int dev,
+CS_Source CreateUsbCameraDev(std::string_view name, int dev,
CS_Status* status) {
- wpi::SmallString<32> path;
- wpi::raw_svector_ostream oss{path};
- oss << "/dev/video" << dev;
- return CreateUsbCameraPath(name, oss.str(), status);
+ return CreateUsbCameraPath(name, fmt::format("/dev/video{}", dev), status);
}
-CS_Source CreateUsbCameraPath(const wpi::Twine& name, const wpi::Twine& path,
+CS_Source CreateUsbCameraPath(std::string_view name, std::string_view path,
CS_Status* status) {
auto& inst = Instance::GetInstance();
return inst.CreateSource(CS_SOURCE_USB, std::make_shared<UsbCameraImpl>(
@@ -1424,7 +1553,7 @@
inst.telemetry, path));
}
-void SetUsbCameraPath(CS_Source source, const wpi::Twine& path,
+void SetUsbCameraPath(CS_Source source, std::string_view path,
CS_Status* status) {
auto data = Instance::GetInstance().GetSource(source);
if (!data || data->kind != CS_SOURCE_USB) {
@@ -1476,7 +1605,9 @@
path += ep->d_name;
char* target = ::realpath(path.c_str(), nullptr);
if (target) {
- if (keypath == target) info.otherPaths.emplace_back(path.str());
+ if (keypath == target) {
+ info.otherPaths.emplace_back(path.str());
+ }
std::free(target);
}
}
@@ -1498,11 +1629,17 @@
if (DIR* dp = ::opendir("/dev")) {
while (struct dirent* ep = ::readdir(dp)) {
- wpi::StringRef fname{ep->d_name};
- if (!fname.startswith("video")) continue;
+ std::string_view fname{ep->d_name};
+ if (!wpi::starts_with(fname, "video")) {
+ continue;
+ }
unsigned int dev = 0;
- if (fname.substr(5).getAsInteger(10, dev)) continue;
+ if (auto v = wpi::parse_integer<unsigned int>(fname.substr(5), 10)) {
+ dev = v.value();
+ } else {
+ continue;
+ }
UsbCameraInfo info;
info.dev = dev;
@@ -1511,20 +1648,26 @@
path += fname;
info.path = path.str();
- if (!IsVideoCaptureDevice(path.c_str())) continue;
+ if (!IsVideoCaptureDevice(path.c_str())) {
+ continue;
+ }
info.name = GetDescriptionImpl(path.c_str());
- if (info.name.empty()) continue;
+ if (info.name.empty()) {
+ continue;
+ }
GetVendorProduct(dev, &info.vendorId, &info.productId);
- if (dev >= retval.size()) retval.resize(info.dev + 1);
+ if (dev >= retval.size()) {
+ retval.resize(info.dev + 1);
+ }
retval[info.dev] = std::move(info);
}
::closedir(dp);
} else {
// *status = ;
- WPI_ERROR(Instance::GetInstance().logger, "Could not open /dev");
+ WPI_ERROR(Instance::GetInstance().logger, "{}", "Could not open /dev");
return retval;
}
@@ -1540,11 +1683,12 @@
path += ep->d_name;
char* target = ::realpath(path.c_str(), nullptr);
if (target) {
- wpi::StringRef fname = wpi::sys::path::filename(target);
- unsigned int dev = 0;
- if (fname.startswith("video") &&
- !fname.substr(5).getAsInteger(10, dev) && dev < retval.size()) {
- retval[dev].otherPaths.emplace_back(path.str());
+ std::string fname = fs::path{target}.filename();
+ std::optional<unsigned int> dev;
+ if (wpi::starts_with(fname, "video") &&
+ (dev = wpi::parse_integer<unsigned int>(fname.substr(5), 10)) &&
+ dev.value() < retval.size()) {
+ retval[dev.value()].otherPaths.emplace_back(path.str());
}
std::free(target);
}
diff --git a/cscore/src/main/native/linux/UsbCameraImpl.h b/cscore/src/main/native/linux/UsbCameraImpl.h
index 62b94a0..a032466 100644
--- a/cscore/src/main/native/linux/UsbCameraImpl.h
+++ b/cscore/src/main/native/linux/UsbCameraImpl.h
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2020 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#ifndef CSCORE_USBCAMERAIMPL_H_
#define CSCORE_USBCAMERAIMPL_H_
@@ -13,13 +10,12 @@
#include <atomic>
#include <memory>
#include <string>
+#include <string_view>
#include <thread>
#include <utility>
#include <vector>
-#include <wpi/STLExtras.h>
#include <wpi/SmallVector.h>
-#include <wpi/Twine.h>
#include <wpi/condition_variable.h>
#include <wpi/mutex.h>
#include <wpi/raw_istream.h>
@@ -36,15 +32,15 @@
class UsbCameraImpl : public SourceImpl {
public:
- UsbCameraImpl(const wpi::Twine& name, wpi::Logger& logger, Notifier& notifier,
- Telemetry& telemetry, const wpi::Twine& path);
+ UsbCameraImpl(std::string_view name, wpi::Logger& logger, Notifier& notifier,
+ Telemetry& telemetry, std::string_view path);
~UsbCameraImpl() override;
void Start() override;
// Property functions
void SetProperty(int property, int value, CS_Status* status) override;
- void SetStringProperty(int property, const wpi::Twine& value,
+ void SetStringProperty(int property, std::string_view value,
CS_Status* status) override;
// Standard common camera properties
@@ -66,7 +62,7 @@
void NumSinksChanged() override;
void NumSinksEnabledChanged() override;
- void SetPath(const wpi::Twine& path, CS_Status* status);
+ void SetPath(std::string_view path, CS_Status* status);
std::string GetPath() const;
// Messages passed to/from camera thread
@@ -98,7 +94,7 @@
protected:
std::unique_ptr<PropertyImpl> CreateEmptyProperty(
- const wpi::Twine& name) const override;
+ std::string_view name) const override;
// Cache properties. Immediately successful if properties are already cached.
// If they are not, tries to connect to the camera to do so; returns false and
diff --git a/cscore/src/main/native/linux/UsbCameraListener.cpp b/cscore/src/main/native/linux/UsbCameraListener.cpp
new file mode 100644
index 0000000..40e84c5
--- /dev/null
+++ b/cscore/src/main/native/linux/UsbCameraListener.cpp
@@ -0,0 +1,56 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+#include "UsbCameraListener.h"
+
+#include <wpi/EventLoopRunner.h>
+#include <wpi/StringExtras.h>
+#include <wpi/uv/FsEvent.h>
+#include <wpi/uv/Timer.h>
+
+#include "Notifier.h"
+
+using namespace cs;
+
+class UsbCameraListener::Impl {
+ public:
+ explicit Impl(Notifier& notifier) : m_notifier(notifier) {}
+
+ Notifier& m_notifier;
+
+ std::unique_ptr<wpi::EventLoopRunner> m_runner;
+};
+
+UsbCameraListener::UsbCameraListener(wpi::Logger& logger, Notifier& notifier)
+ : m_impl(std::make_unique<Impl>(notifier)) {}
+
+UsbCameraListener::~UsbCameraListener() = default;
+
+void UsbCameraListener::Start() {
+ if (!m_impl->m_runner) {
+ m_impl->m_runner = std::make_unique<wpi::EventLoopRunner>();
+ m_impl->m_runner->ExecAsync([impl = m_impl.get()](wpi::uv::Loop& loop) {
+ auto refreshTimer = wpi::uv::Timer::Create(loop);
+ refreshTimer->timeout.connect([notifier = &impl->m_notifier] {
+ notifier->NotifyUsbCamerasChanged();
+ });
+ refreshTimer->Unreference();
+
+ auto devEvents = wpi::uv::FsEvent::Create(loop);
+ devEvents->fsEvent.connect([refreshTimer](const char* fn, int flags) {
+ if (wpi::starts_with(fn, "video")) {
+ refreshTimer->Start(wpi::uv::Timer::Time(200));
+ }
+ });
+ devEvents->Start("/dev");
+ devEvents->Unreference();
+ });
+ }
+}
+
+void UsbCameraListener::Stop() {
+ if (m_impl->m_runner) {
+ m_impl->m_runner.reset();
+ }
+}
diff --git a/cscore/src/main/native/linux/UsbCameraProperty.cpp b/cscore/src/main/native/linux/UsbCameraProperty.cpp
index 4dfa39c..149ca1b 100644
--- a/cscore/src/main/native/linux/UsbCameraProperty.cpp
+++ b/cscore/src/main/native/linux/UsbCameraProperty.cpp
@@ -1,14 +1,11 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#include "UsbCameraProperty.h"
+#include <fmt/format.h>
#include <wpi/SmallString.h>
-#include <wpi/raw_ostream.h>
#include "UsbUtil.h"
@@ -29,7 +26,9 @@
ctrls.count = 1;
ctrls.controls = &ctrl;
int rc = DoIoctl(fd, VIDIOC_G_EXT_CTRLS, &ctrls);
- if (rc < 0) return rc;
+ if (rc < 0) {
+ return rc;
+ }
*value = ctrl.value;
} else {
// Use normal control
@@ -37,7 +36,9 @@
std::memset(&ctrl, 0, sizeof(ctrl));
ctrl.id = id;
int rc = DoIoctl(fd, VIDIOC_G_CTRL, &ctrl);
- if (rc < 0) return rc;
+ if (rc < 0) {
+ return rc;
+ }
*value = ctrl.value;
}
return 0;
@@ -54,10 +55,11 @@
std::memset(&ctrl, 0, sizeof(ctrl));
std::memset(&ctrls, 0, sizeof(ctrls));
ctrl.id = id;
- if (type == V4L2_CTRL_TYPE_INTEGER64)
+ if (type == V4L2_CTRL_TYPE_INTEGER64) {
ctrl.value64 = value;
- else
+ } else {
ctrl.value = static_cast<__s32>(value);
+ }
ctrls.ctrl_class = ctrl_class;
ctrls.count = 1;
ctrls.controls = &ctrl;
@@ -90,15 +92,8 @@
}
static int SetStringCtrlIoctl(int fd, int id, int maximum,
- const wpi::Twine& value) {
- wpi::SmallString<64> strBuf, strBuf2;
- wpi::StringRef str = value.toNullTerminatedStringRef(strBuf);
- if (str.size() > static_cast<size_t>(maximum)) {
- // don't know if strBuf was used, just recopy
- strBuf2 = str.take_front(maximum);
- str = strBuf2;
- strBuf2.push_back('\0'); // null terminate
- }
+ std::string_view value) {
+ wpi::SmallString<64> str{value.substr(0, maximum)};
struct v4l2_ext_control ctrl;
struct v4l2_ext_controls ctrls;
@@ -106,7 +101,7 @@
std::memset(&ctrls, 0, sizeof(ctrls));
ctrl.id = id;
ctrl.size = str.size();
- ctrl.string = const_cast<char*>(str.data());
+ ctrl.string = const_cast<char*>(str.c_str());
ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(id);
ctrls.count = 1;
ctrls.controls = &ctrl;
@@ -115,25 +110,26 @@
// Removes non-alphanumeric characters and replaces spaces with underscores.
// e.g. "Zoom, Absolute" -> "zoom_absolute", "Pan (Absolute)" -> "pan_absolute"
-static wpi::StringRef NormalizeName(wpi::StringRef name,
- wpi::SmallVectorImpl<char>& buf) {
+static std::string_view NormalizeName(std::string_view name,
+ wpi::SmallVectorImpl<char>& buf) {
bool newWord = false;
for (auto ch : name) {
if (std::isalnum(ch)) {
- if (newWord) buf.push_back('_');
+ if (newWord) {
+ buf.push_back('_');
+ }
newWord = false;
buf.push_back(std::tolower(ch));
} else if (!buf.empty()) {
newWord = true;
}
}
- return wpi::StringRef(buf.data(), buf.size());
+ return {buf.data(), buf.size()};
}
#ifdef VIDIOC_QUERY_EXT_CTRL
UsbCameraProperty::UsbCameraProperty(const struct v4l2_query_ext_ctrl& ctrl)
- : PropertyImpl(wpi::StringRef{}, CS_PROP_NONE, ctrl.step,
- ctrl.default_value, 0),
+ : PropertyImpl({}, CS_PROP_NONE, ctrl.step, ctrl.default_value, 0),
id(ctrl.id & V4L2_CTRL_ID_MASK),
type(ctrl.type) {
hasMinimum = true;
@@ -166,15 +162,16 @@
// name
size_t len = 0;
- while (len < sizeof(ctrl.name) && ctrl.name[len] != '\0') ++len;
+ while (len < sizeof(ctrl.name) && ctrl.name[len] != '\0') {
+ ++len;
+ }
wpi::SmallString<64> name_buf;
- name = NormalizeName(wpi::StringRef(ctrl.name, len), name_buf);
+ name = NormalizeName({ctrl.name, len}, name_buf);
}
#endif
UsbCameraProperty::UsbCameraProperty(const struct v4l2_queryctrl& ctrl)
- : PropertyImpl(wpi::StringRef{}, CS_PROP_NONE, ctrl.step,
- ctrl.default_value, 0),
+ : PropertyImpl({}, CS_PROP_NONE, ctrl.step, ctrl.default_value, 0),
id(ctrl.id & V4L2_CTRL_ID_MASK),
type(ctrl.type) {
hasMinimum = true;
@@ -204,10 +201,12 @@
// name
size_t len = 0;
- while (len < sizeof(ctrl.name) && ctrl.name[len] != '\0') ++len;
+ while (len < sizeof(ctrl.name) && ctrl.name[len] != '\0') {
+ ++len;
+ }
wpi::SmallString<64> name_buf;
- name = NormalizeName(
- wpi::StringRef(reinterpret_cast<const char*>(ctrl.name), len), name_buf);
+ name =
+ NormalizeName({reinterpret_cast<const char*>(ctrl.name), len}, name_buf);
}
std::unique_ptr<UsbCameraProperty> UsbCameraProperty::DeviceQuery(int fd,
@@ -222,7 +221,9 @@
if (rc == 0) {
*id = qc_ext.id; // copy back
// We don't support array types
- if (qc_ext.elems > 1 || qc_ext.nr_of_dims > 0) return nullptr;
+ if (qc_ext.elems > 1 || qc_ext.nr_of_dims > 0) {
+ return nullptr;
+ }
prop = std::make_unique<UsbCameraProperty>(qc_ext);
}
#endif
@@ -233,7 +234,9 @@
qc.id = *id;
rc = TryIoctl(fd, VIDIOC_QUERYCTRL, &qc);
*id = qc.id; // copy back
- if (rc != 0) return nullptr;
+ if (rc != 0) {
+ return nullptr;
+ }
prop = std::make_unique<UsbCameraProperty>(qc);
}
@@ -245,10 +248,11 @@
qmenu.id = *id;
for (int i = prop->minimum; i <= prop->maximum; ++i) {
qmenu.index = static_cast<__u32>(i);
- if (TryIoctl(fd, VIDIOC_QUERYMENU, &qmenu) != 0) continue;
+ if (TryIoctl(fd, VIDIOC_QUERYMENU, &qmenu) != 0) {
+ continue;
+ }
if (prop->intMenu) {
- wpi::raw_string_ostream os(prop->enumChoices[i]);
- os << qmenu.value;
+ prop->enumChoices[i] = fmt::to_string(qmenu.value);
} else {
prop->enumChoices[i] = reinterpret_cast<const char*>(qmenu.name);
}
@@ -259,7 +263,9 @@
}
bool UsbCameraProperty::DeviceGet(std::unique_lock<wpi::mutex>& lock, int fd) {
- if (fd < 0) return true;
+ if (fd < 0) {
+ return true;
+ }
unsigned idCopy = id;
int rv = 0;
@@ -272,7 +278,9 @@
lock.unlock();
rv = GetIntCtrlIoctl(fd, idCopy, typeCopy, &newValue);
lock.lock();
- if (rv >= 0) value = newValue;
+ if (rv >= 0) {
+ value = newValue;
+ }
break;
}
case CS_PROP_STRING: {
@@ -281,7 +289,9 @@
lock.unlock();
rv = GetStringCtrlIoctl(fd, idCopy, maximumCopy, &newValueStr);
lock.lock();
- if (rv >= 0) valueStr = std::move(newValueStr);
+ if (rv >= 0) {
+ valueStr = std::move(newValueStr);
+ }
break;
}
default:
@@ -295,13 +305,15 @@
int fd) const {
// Make a copy of the string as we're about to release the lock
wpi::SmallString<128> valueStrCopy{valueStr};
- return DeviceSet(lock, fd, value, valueStrCopy);
+ return DeviceSet(lock, fd, value, valueStrCopy.str());
}
bool UsbCameraProperty::DeviceSet(std::unique_lock<wpi::mutex>& lock, int fd,
int newValue,
- const wpi::Twine& newValueStr) const {
- if (!device || fd < 0) return true;
+ std::string_view newValueStr) const {
+ if (!device || fd < 0) {
+ return true;
+ }
unsigned idCopy = id;
int rv = 0;
diff --git a/cscore/src/main/native/linux/UsbCameraProperty.h b/cscore/src/main/native/linux/UsbCameraProperty.h
index 32c5e19..b0291a1 100644
--- a/cscore/src/main/native/linux/UsbCameraProperty.h
+++ b/cscore/src/main/native/linux/UsbCameraProperty.h
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#ifndef CSCORE_USBCAMERAPROPERTY_H_
#define CSCORE_USBCAMERAPROPERTY_H_
@@ -11,6 +8,7 @@
#include <linux/videodev2.h>
#include <memory>
+#include <string_view>
#include <wpi/mutex.h>
@@ -22,19 +20,19 @@
class UsbCameraProperty : public PropertyImpl {
public:
UsbCameraProperty() = default;
- explicit UsbCameraProperty(const wpi::Twine& name_) : PropertyImpl{name_} {}
+ explicit UsbCameraProperty(std::string_view name_) : PropertyImpl{name_} {}
// Software property constructor
- UsbCameraProperty(const wpi::Twine& name_, unsigned id_,
- CS_PropertyKind kind_, int minimum_, int maximum_,
- int step_, int defaultValue_, int value_)
+ UsbCameraProperty(std::string_view name_, unsigned id_, CS_PropertyKind kind_,
+ int minimum_, int maximum_, int step_, int defaultValue_,
+ int value_)
: PropertyImpl(name_, kind_, minimum_, maximum_, step_, defaultValue_,
value_),
device{false},
id{id_} {}
// Normalized property constructor
- UsbCameraProperty(const wpi::Twine& name_, int rawIndex_,
+ UsbCameraProperty(std::string_view name_, int rawIndex_,
const UsbCameraProperty& rawProp, int defaultValue_,
int value_)
: PropertyImpl(name_, rawProp.propKind, 1, defaultValue_, value_),
@@ -58,7 +56,7 @@
bool DeviceGet(std::unique_lock<wpi::mutex>& lock, int fd);
bool DeviceSet(std::unique_lock<wpi::mutex>& lock, int fd) const;
bool DeviceSet(std::unique_lock<wpi::mutex>& lock, int fd, int newValue,
- const wpi::Twine& newValueStr) const;
+ std::string_view newValueStr) const;
// If this is a device (rather than software) property
bool device{true};
diff --git a/cscore/src/main/native/linux/UsbUtil.cpp b/cscore/src/main/native/linux/UsbUtil.cpp
index ac48178..afe3e42 100644
--- a/cscore/src/main/native/linux/UsbUtil.cpp
+++ b/cscore/src/main/native/linux/UsbUtil.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2018 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#include "UsbUtil.h"
@@ -11,8 +8,10 @@
#include <libgen.h>
#include <sys/ioctl.h>
-#include <wpi/Format.h>
+#include <fmt/format.h>
#include <wpi/SmallString.h>
+#include <wpi/StringExtras.h>
+#include <wpi/fs.h>
#include <wpi/raw_istream.h>
#include <wpi/raw_ostream.h>
@@ -21,139 +20,142 @@
namespace cs {
-static wpi::StringRef GetUsbNameFromFile(int vendor, int product,
- wpi::SmallVectorImpl<char>& buf) {
+static std::string GetUsbNameFromFile(int vendor, int product) {
int fd = open("/var/lib/usbutils/usb.ids", O_RDONLY);
- if (fd < 0) return wpi::StringRef{};
+ if (fd < 0) {
+ return {};
+ }
- wpi::raw_svector_ostream os{buf};
+ wpi::SmallString<128> buf;
wpi::raw_fd_istream is{fd, true};
// build vendor and product 4-char hex strings
- wpi::SmallString<16> vendorStr, productStr;
- wpi::raw_svector_ostream vendorOs{vendorStr}, productOs{productStr};
- vendorOs << wpi::format_hex_no_prefix(vendor, 4);
- productOs << wpi::format_hex_no_prefix(product, 4);
+ auto vendorStr = fmt::format("{:04x}", vendor);
+ auto productStr = fmt::format("{:04x}", product);
// scan file
wpi::SmallString<128> lineBuf;
bool foundVendor = false;
for (;;) {
auto line = is.getline(lineBuf, 4096);
- if (is.has_error()) break;
+ if (is.has_error()) {
+ break;
+ }
- if (line.empty()) continue;
+ if (line.empty()) {
+ continue;
+ }
// look for vendor at start of line
- if (line.startswith(vendorStr)) {
+ if (wpi::starts_with(line, vendorStr)) {
foundVendor = true;
- os << line.substr(5).trim() << ' ';
+ buf += wpi::trim(line.substr(5));
+ buf += ' ';
continue;
}
if (foundVendor) {
// next vendor, but didn't match product?
if (line[0] != '\t') {
- os << "Unknown";
- return os.str();
+ buf += "Unknown";
+ return buf;
}
// look for product
- if (line.substr(1).startswith(productStr)) {
- os << line.substr(6).trim();
- return os.str();
+ if (wpi::starts_with(line.substr(1), productStr)) {
+ buf += wpi::trim(line.substr(6));
+ return buf;
}
}
}
- return wpi::StringRef{};
+ return {};
}
-wpi::StringRef GetUsbNameFromId(int vendor, int product,
- wpi::SmallVectorImpl<char>& buf) {
+std::string GetUsbNameFromId(int vendor, int product) {
// try reading usb.ids
- wpi::StringRef rv = GetUsbNameFromFile(vendor, product, buf);
- if (!rv.empty()) return rv;
-
- // Fall back to internal database
- wpi::raw_svector_ostream os{buf};
- switch (vendor) {
- case 0x046d:
- os << "Logitech, Inc. ";
- switch (product) {
- case 0x0802:
- os << "Webcam C200";
- break;
- case 0x0804:
- os << "Webcam C250";
- break;
- case 0x0805:
- os << "Webcam C300";
- break;
- case 0x0807:
- os << "Webcam B500";
- break;
- case 0x0808:
- os << "Webcam C600";
- break;
- case 0x0809:
- os << "Webcam Pro 9000";
- break;
- case 0x080a:
- os << "Portable Webcam C905";
- break;
- case 0x080f:
- os << "Webcam C120";
- break;
- case 0x0819:
- os << "Webcam C210";
- break;
- case 0x081b:
- os << "Webcam C310";
- break;
- case 0x081d:
- os << "HD Webcam C510";
- break;
- case 0x0821:
- os << "HD Webcam C910";
- break;
- case 0x0825:
- os << "Webcam C270";
- break;
- case 0x0826:
- os << "HD Webcam C525";
- break;
- case 0x0828:
- os << "HD Webcam B990";
- break;
- case 0x082b:
- os << "Webcam C170";
- break;
- case 0x082d:
- os << "HD Pro Webcam C920";
- break;
- case 0x0836:
- os << "B525 HD Webcam";
- break;
- case 0x0843:
- os << "Webcam C930e";
- break;
- }
- break;
+ std::string rv = GetUsbNameFromFile(vendor, product);
+ if (!rv.empty()) {
+ return rv;
}
- return os.str();
+ // Fall back to internal database
+ switch (vendor) {
+ case 0x046d: {
+ std::string_view productStr;
+ switch (product) {
+ case 0x0802:
+ productStr = "Webcam C200";
+ break;
+ case 0x0804:
+ productStr = "Webcam C250";
+ break;
+ case 0x0805:
+ productStr = "Webcam C300";
+ break;
+ case 0x0807:
+ productStr = "Webcam B500";
+ break;
+ case 0x0808:
+ productStr = "Webcam C600";
+ break;
+ case 0x0809:
+ productStr = "Webcam Pro 9000";
+ break;
+ case 0x080a:
+ productStr = "Portable Webcam C905";
+ break;
+ case 0x080f:
+ productStr = "Webcam C120";
+ break;
+ case 0x0819:
+ productStr = "Webcam C210";
+ break;
+ case 0x081b:
+ productStr = "Webcam C310";
+ break;
+ case 0x081d:
+ productStr = "HD Webcam C510";
+ break;
+ case 0x0821:
+ productStr = "HD Webcam C910";
+ break;
+ case 0x0825:
+ productStr = "Webcam C270";
+ break;
+ case 0x0826:
+ productStr = "HD Webcam C525";
+ break;
+ case 0x0828:
+ productStr = "HD Webcam B990";
+ break;
+ case 0x082b:
+ productStr = "Webcam C170";
+ break;
+ case 0x082d:
+ productStr = "HD Pro Webcam C920";
+ break;
+ case 0x0836:
+ productStr = "B525 HD Webcam";
+ break;
+ case 0x0843:
+ productStr = "Webcam C930e";
+ break;
+ }
+ return fmt::format("Logitech, Inc. {}", productStr);
+ }
+ }
+
+ return {};
}
int CheckedIoctl(int fd, unsigned long req, void* data, // NOLINT(runtime/int)
const char* name, const char* file, int line, bool quiet) {
int retval = ioctl(fd, req, data);
if (!quiet && retval < 0) {
- wpi::SmallString<64> localfile{file};
- localfile.push_back('\0');
- WPI_ERROR(Instance::GetInstance().logger,
- "ioctl " << name << " failed at " << basename(localfile.data())
- << ":" << line << ": " << std::strerror(errno));
+ WPI_ERROR(Instance::GetInstance().logger, "ioctl {} failed at {}:{}: {}",
+ name, fs::path{file}.filename().string(), line,
+ std::strerror(errno));
}
return retval;
}
diff --git a/cscore/src/main/native/linux/UsbUtil.h b/cscore/src/main/native/linux/UsbUtil.h
index 4f1d9d8..9f6f8f5 100644
--- a/cscore/src/main/native/linux/UsbUtil.h
+++ b/cscore/src/main/native/linux/UsbUtil.h
@@ -1,22 +1,15 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2018 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#ifndef CSCORE_USBUTIL_H_
#define CSCORE_USBUTIL_H_
-#include <stdint.h>
-
-#include <wpi/SmallVector.h>
-#include <wpi/StringRef.h>
+#include <string>
namespace cs {
-wpi::StringRef GetUsbNameFromId(int vendor, int product,
- wpi::SmallVectorImpl<char>& buf);
+std::string GetUsbNameFromId(int vendor, int product);
int CheckedIoctl(int fd, unsigned long req, void* data, // NOLINT(runtime/int)
const char* name, const char* file, int line, bool quiet);
diff --git a/cscore/src/main/native/osx/NetworkListener.cpp b/cscore/src/main/native/osx/NetworkListener.cpp
index 0716789..3d77fba 100644
--- a/cscore/src/main/native/osx/NetworkListener.cpp
+++ b/cscore/src/main/native/osx/NetworkListener.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2015-2018 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#include "NetworkListener.h"
@@ -13,7 +10,7 @@
NetworkListener::NetworkListener(wpi::Logger& logger, Notifier& notifier) {}
-NetworkListener::~NetworkListener() {}
+NetworkListener::~NetworkListener() = default;
void NetworkListener::Start() {}
diff --git a/cscore/src/main/native/osx/NetworkUtil.cpp b/cscore/src/main/native/osx/NetworkUtil.cpp
index 935c21f..0aaf535 100644
--- a/cscore/src/main/native/osx/NetworkUtil.cpp
+++ b/cscore/src/main/native/osx/NetworkUtil.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2018 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#include "cscore_cpp.h"
diff --git a/cscore/src/main/native/osx/UsbCameraImpl.cpp b/cscore/src/main/native/osx/UsbCameraImpl.cpp
index abefcc7..3b5d821 100644
--- a/cscore/src/main/native/osx/UsbCameraImpl.cpp
+++ b/cscore/src/main/native/osx/UsbCameraImpl.cpp
@@ -1,27 +1,24 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2020 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#include "cscore_cpp.h"
namespace cs {
-CS_Source CreateUsbCameraDev(const wpi::Twine& name, int dev,
+CS_Source CreateUsbCameraDev(std::string_view name, int dev,
CS_Status* status) {
*status = CS_INVALID_HANDLE;
return 0;
}
-CS_Source CreateUsbCameraPath(const wpi::Twine& name, const wpi::Twine& path,
+CS_Source CreateUsbCameraPath(std::string_view name, std::string_view path,
CS_Status* status) {
*status = CS_INVALID_HANDLE;
return 0;
}
-void SetUsbCameraPath(CS_Source source, const wpi::Twine& path,
+void SetUsbCameraPath(CS_Source source, std::string_view path,
CS_Status* status) {
*status = CS_INVALID_HANDLE;
}
diff --git a/cscore/src/main/native/osx/UsbCameraListener.cpp b/cscore/src/main/native/osx/UsbCameraListener.cpp
new file mode 100644
index 0000000..b83663d
--- /dev/null
+++ b/cscore/src/main/native/osx/UsbCameraListener.cpp
@@ -0,0 +1,17 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+#include "UsbCameraListener.h"
+
+using namespace cs;
+
+class UsbCameraListener::Impl {};
+
+UsbCameraListener::UsbCameraListener(wpi::Logger& logger, Notifier& notifier) {}
+
+UsbCameraListener::~UsbCameraListener() = default;
+
+void UsbCameraListener::Start() {}
+
+void UsbCameraListener::Stop() {}
diff --git a/cscore/src/main/native/windows/COMCreators.cpp b/cscore/src/main/native/windows/COMCreators.cpp
index 265f7d3..f9f5cae 100644
--- a/cscore/src/main/native/windows/COMCreators.cpp
+++ b/cscore/src/main/native/windows/COMCreators.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2018 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#include <mfapi.h>
#include <mfidl.h>
@@ -59,9 +56,13 @@
return uCount;
}
-STDMETHODIMP SourceReaderCB::OnEvent(DWORD, IMFMediaEvent*) { return S_OK; }
+STDMETHODIMP SourceReaderCB::OnEvent(DWORD, IMFMediaEvent*) {
+ return S_OK;
+}
-STDMETHODIMP SourceReaderCB::OnFlush(DWORD) { return S_OK; }
+STDMETHODIMP SourceReaderCB::OnFlush(DWORD) {
+ return S_OK;
+}
void SourceReaderCB::NotifyError(HRESULT hr) {
wprintf(L"Source Reader error: 0x%X\n", hr);
@@ -73,7 +74,8 @@
IMFSample* pSample // Can be NULL
) {
auto source = m_source.lock();
- if (!source) return S_OK;
+ if (!source)
+ return S_OK;
if (SUCCEEDED(hrStatus)) {
if (pSample) {
// Prcoess sample
diff --git a/cscore/src/main/native/windows/COMCreators.h b/cscore/src/main/native/windows/COMCreators.h
index f89e6fd..84cb982 100644
--- a/cscore/src/main/native/windows/COMCreators.h
+++ b/cscore/src/main/native/windows/COMCreators.h
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2018 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#pragma once
@@ -42,7 +39,7 @@
private:
// Destructor is private. Caller should call Release.
- virtual ~SourceReaderCB() {}
+ virtual ~SourceReaderCB() = default;
void NotifyError(HRESULT hr);
ULONG m_nRefCount;
diff --git a/cscore/src/main/native/windows/ComPtr.h b/cscore/src/main/native/windows/ComPtr.h
index 22a330d..2d9f241 100644
--- a/cscore/src/main/native/windows/ComPtr.h
+++ b/cscore/src/main/native/windows/ComPtr.h
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2018 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#pragma once
@@ -27,24 +24,24 @@
template <typename T>
friend class ComPtr;
- ComPtr(std::nullptr_t = nullptr) noexcept {} // NOLINT(runtime/explicit)
+ ComPtr(std::nullptr_t = nullptr) noexcept {} // NOLINT
ComPtr(const ComPtr& other) noexcept : m_ptr(other.m_ptr) {
InternalAddRef();
}
template <typename T>
- ComPtr(const ComPtr<T>& other) noexcept : m_ptr(other.m_ptr) {
+ ComPtr(const ComPtr<T>& other) noexcept : m_ptr(other.m_ptr) { // NOLINT
InternalAddRef();
}
template <typename T>
- ComPtr(ComPtr<T>&& other) noexcept : m_ptr(other.m_ptr) {
+ ComPtr(ComPtr<T>&& other) noexcept : m_ptr(other.m_ptr) { // NOLINT
other.m_ptr = nullptr;
}
~ComPtr() noexcept { InternalRelease(); }
- ComPtr& operator=(const ComPtr& other) noexcept {
+ ComPtr& operator=(const ComPtr& other) noexcept { // NOLINT
InternalCopy(other.m_ptr);
return *this;
}
diff --git a/cscore/src/main/native/windows/NetworkListener.cpp b/cscore/src/main/native/windows/NetworkListener.cpp
index cd29e44..b4fbb1e 100644
--- a/cscore/src/main/native/windows/NetworkListener.cpp
+++ b/cscore/src/main/native/windows/NetworkListener.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2015-2018 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#include "NetworkListener.h"
@@ -47,7 +44,9 @@
NetworkListener::NetworkListener(wpi::Logger& logger, Notifier& notifier)
: m_impl(std::make_unique<Impl>(logger, notifier)) {}
-NetworkListener::~NetworkListener() { Stop(); }
+NetworkListener::~NetworkListener() {
+ Stop();
+}
void NetworkListener::Start() {
NotifyIpInterfaceChange(AF_INET, OnInterfaceChange, &m_impl->m_notifier, true,
diff --git a/cscore/src/main/native/windows/NetworkUtil.cpp b/cscore/src/main/native/windows/NetworkUtil.cpp
index 151ba79..86b99bc 100644
--- a/cscore/src/main/native/windows/NetworkUtil.cpp
+++ b/cscore/src/main/native/windows/NetworkUtil.cpp
@@ -1,11 +1,9 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#include <uv.h>
+#include <ws2tcpip.h>
#include "cscore_cpp.h"
@@ -24,7 +22,9 @@
char ip[50];
for (int i = 0; i < counts; i++) {
- if (adrs[i].is_internal) continue;
+ if (adrs[i].is_internal) {
+ continue;
+ }
InetNtop(PF_INET, &(adrs[i].netmask.netmask4.sin_addr.s_addr), ip,
sizeof(ip) - 1);
ip[49] = '\0';
diff --git a/cscore/src/main/native/windows/UsbCameraImpl.cpp b/cscore/src/main/native/windows/UsbCameraImpl.cpp
index 784f5ad..1a3b230 100644
--- a/cscore/src/main/native/windows/UsbCameraImpl.cpp
+++ b/cscore/src/main/native/windows/UsbCameraImpl.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2018-2020 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#define _WINSOCKAPI_
#include "UsbCameraImpl.h"
@@ -29,8 +26,7 @@
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <wpi/MemAlloc.h>
-#include <wpi/SmallString.h>
-#include <wpi/raw_ostream.h>
+#include <wpi/StringExtras.h>
#include <wpi/timestamp.h>
#include "COMCreators.h"
@@ -72,24 +68,26 @@
namespace cs {
-UsbCameraImpl::UsbCameraImpl(const wpi::Twine& name, wpi::Logger& logger,
+UsbCameraImpl::UsbCameraImpl(std::string_view name, wpi::Logger& logger,
Notifier& notifier, Telemetry& telemetry,
- const wpi::Twine& path)
- : SourceImpl{name, logger, notifier, telemetry}, m_path{path.str()} {
+ std::string_view path)
+ : SourceImpl{name, logger, notifier, telemetry}, m_path{path} {
std::wstring_convert<std::codecvt_utf8<wchar_t>> utf8_conv;
m_widePath = utf8_conv.from_bytes(m_path.c_str());
m_deviceId = -1;
StartMessagePump();
}
-UsbCameraImpl::UsbCameraImpl(const wpi::Twine& name, wpi::Logger& logger,
+UsbCameraImpl::UsbCameraImpl(std::string_view name, wpi::Logger& logger,
Notifier& notifier, Telemetry& telemetry,
int deviceId)
: SourceImpl{name, logger, notifier, telemetry}, m_deviceId(deviceId) {
StartMessagePump();
}
-UsbCameraImpl::~UsbCameraImpl() { m_messagePump = nullptr; }
+UsbCameraImpl::~UsbCameraImpl() {
+ m_messagePump = nullptr;
+}
void UsbCameraImpl::SetProperty(int property, int value, CS_Status* status) {
Message msg{Message::kCmdSetProperty};
@@ -100,11 +98,11 @@
SetCameraMessage, msg.kind, &msg);
*status = result;
}
-void UsbCameraImpl::SetStringProperty(int property, const wpi::Twine& value,
+void UsbCameraImpl::SetStringProperty(int property, std::string_view value,
CS_Status* status) {
Message msg{Message::kCmdSetPropertyStr};
msg.data[0] = property;
- msg.dataStr = value.str();
+ msg.dataStr = value;
auto result =
m_messagePump->SendWindowMessage<CS_Status, Message::Kind, Message*>(
SetCameraMessage, msg.kind, &msg);
@@ -198,9 +196,9 @@
SetCameraMessage, Message::kNumSinksEnabledChanged, nullptr);
}
-void UsbCameraImpl::SetPath(const wpi::Twine& path, CS_Status* status) {
+void UsbCameraImpl::SetPath(std::string_view path, CS_Status* status) {
Message msg{Message::kCmdSetPath};
- msg.dataStr = path.str();
+ msg.dataStr = path;
auto result =
m_messagePump->SendWindowMessage<CS_Status, Message::Kind, Message*>(
SetCameraMessage, msg.kind, &msg);
@@ -257,7 +255,8 @@
}
void UsbCameraImpl::DeviceDisconnect() {
- if (m_connectVerbose) SINFO("Disconnected from " << m_path);
+ if (m_connectVerbose)
+ SINFO("Disconnected from {}", m_path);
m_sourceReader.Reset();
m_mediaSource.Reset();
if (m_imageCallback) {
@@ -268,8 +267,9 @@
SetConnected(false);
}
-static bool IsPercentageProperty(wpi::StringRef name) {
- if (name.startswith("raw_")) name = name.substr(4);
+static bool IsPercentageProperty(std::string_view name) {
+ if (wpi::starts_with(name, "raw_"))
+ name = name.substr(4);
return name == "Brightness" || name == "Contrast" || name == "Saturation" ||
name == "Hue" || name == "Sharpness" || name == "Gain" ||
name == "Exposure";
@@ -277,43 +277,60 @@
void UsbCameraImpl::ProcessFrame(IMFSample* videoSample,
const VideoMode& mode) {
- if (!videoSample) return;
+ if (!videoSample)
+ return;
ComPtr<IMFMediaBuffer> buf;
if (!SUCCEEDED(videoSample->ConvertToContiguousBuffer(buf.GetAddressOf()))) {
DWORD bcnt = 0;
- if (!SUCCEEDED(videoSample->GetBufferCount(&bcnt))) return;
- if (bcnt == 0) return;
+ if (!SUCCEEDED(videoSample->GetBufferCount(&bcnt)))
+ return;
+ if (bcnt == 0)
+ return;
if (!SUCCEEDED(videoSample->GetBufferByIndex(0, buf.GetAddressOf())))
return;
}
- bool lock2d = false;
BYTE* ptr = NULL;
LONG pitch = 0;
- DWORD maxsize = 0, cursize = 0;
+ DWORD length = 0;
- // "For 2-D buffers, the Lock2D method is more efficient than the Lock
- // method" see IMFMediaBuffer::Lock method documentation:
- // https://msdn.microsoft.com/en-us/library/windows/desktop/bb970366(v=vs.85).aspx
- ComPtr<IMF2DBuffer> buffer2d;
- DWORD memLength2d = 0;
- if (true) {
- buffer2d = buf.As<IMF2DBuffer>();
- if (buffer2d) {
- buffer2d->GetContiguousLength(&memLength2d);
- if (SUCCEEDED(buffer2d->Lock2D(&ptr, &pitch))) {
- lock2d = true;
+ // First try to access using Lock2DSize, then try Lock2D, then fallback
+ // https://docs.microsoft.com/en-us/windows/win32/api/mfobjects/nf-mfobjects-imfmediabuffer-lock
+
+ ComPtr<IMF2DBuffer> buffer2d = buf.As<IMF2DBuffer>();
+ if (buffer2d) {
+ BYTE* scanline0 = nullptr;
+ HRESULT result;
+ ComPtr<IMF2DBuffer2> buffer2d2 = buf.As<IMF2DBuffer2>();
+ if (buffer2d2) {
+ BYTE* datastart;
+ result = buffer2d2->Lock2DSize(MF2DBuffer_LockFlags_Read, &scanline0,
+ &pitch, &datastart, &length);
+ } else {
+ result = buffer2d->Lock2D(&scanline0, &pitch);
+ }
+ if (SUCCEEDED(result)) {
+ BOOL isContiguous;
+ if (pitch > 0 && SUCCEEDED(buffer2d->IsContiguousFormat(&isContiguous)) &&
+ isContiguous &&
+ (length || SUCCEEDED(buffer2d->GetContiguousLength(&length)))) {
+ // Use the buffer pointer.
+ ptr = scanline0;
+ } else {
+ // Release the buffer and fall back to Lock().
+ buffer2d->Unlock2D();
}
}
}
if (ptr == NULL) {
- if (!SUCCEEDED(buf->Lock(&ptr, &maxsize, &cursize))) {
+ buffer2d = nullptr;
+ DWORD maxsize = 0;
+ if (!SUCCEEDED(buf->Lock(&ptr, &maxsize, &length))) {
return;
}
}
- if (!ptr) return;
cv::Mat tmpMat;
std::unique_ptr<Image> dest;
@@ -323,8 +340,7 @@
case cs::VideoMode::PixelFormat::kMJPEG: {
// Special case
PutFrame(VideoMode::kMJPEG, mode.width, mode.height,
- wpi::StringRef(reinterpret_cast<char*>(ptr), cursize),
- wpi::Now());
+ {reinterpret_cast<char*>(ptr), length}, wpi::Now());
doFinalSet = false;
break;
}
@@ -355,10 +371,11 @@
PutFrame(std::move(dest), wpi::Now());
}
- if (lock2d)
+ if (buffer2d) {
buffer2d->Unlock2D();
- else
+ } else {
buf->Unlock();
+ }
}
LRESULT UsbCameraImpl::PumpMain(HWND hwnd, UINT uiMsg, WPARAM wParam,
@@ -454,16 +471,19 @@
}
bool UsbCameraImpl::DeviceConnect() {
- if (m_mediaSource && m_sourceReader) return true;
+ if (m_mediaSource && m_sourceReader)
+ return true;
- if (m_connectVerbose) SINFO("Connecting to USB camera on " << m_path);
+ if (m_connectVerbose)
+ SINFO("Connecting to USB camera on {}", m_path);
- SDEBUG3("opening device");
+ SDEBUG3("{}", "opening device");
const wchar_t* path = m_widePath.c_str();
m_mediaSource = CreateVideoCaptureDevice(path);
- if (!m_mediaSource) return false;
+ if (!m_mediaSource)
+ return false;
m_imageCallback = CreateSourceReaderCB(shared_from_this(), m_mode);
m_sourceReader =
@@ -484,13 +504,13 @@
}
if (!m_properties_cached) {
- SDEBUG3("caching properties");
+ SDEBUG3("{}", "caching properties");
DeviceCacheProperties();
DeviceCacheVideoModes();
DeviceCacheMode();
m_properties_cached = true;
} else {
- SDEBUG3("restoring video mode");
+ SDEBUG3("{}", "restoring video mode");
DeviceSetMode();
}
@@ -504,7 +524,7 @@
}
std::unique_ptr<PropertyImpl> UsbCameraImpl::CreateEmptyProperty(
- const wpi::Twine& name) const {
+ std::string_view name) const {
return nullptr;
}
@@ -513,7 +533,9 @@
auto result = m_messagePump->SendWindowMessage<CS_Status>(
WaitForStartupMessage, nullptr, nullptr);
*status = result;
- if (*status != CS_OK) return false;
+ if (*status != CS_OK) {
+ return false;
+ }
if (!m_properties_cached) {
*status = CS_SOURCE_IS_DISCONNECTED;
return false;
@@ -522,7 +544,7 @@
}
template <typename TagProperty, typename IAM>
-void UsbCameraImpl::DeviceAddProperty(const wpi::Twine& name_, TagProperty tag,
+void UsbCameraImpl::DeviceAddProperty(std::string_view name_, TagProperty tag,
IAM* pProcAmp) {
// First see if properties exist
bool isValid = false;
@@ -533,11 +555,11 @@
}
}
-template void UsbCameraImpl::DeviceAddProperty(const wpi::Twine& name_,
+template void UsbCameraImpl::DeviceAddProperty(std::string_view name_,
tagVideoProcAmpProperty tag,
IAMVideoProcAmp* pProcAmp);
-template void UsbCameraImpl::DeviceAddProperty(const wpi::Twine& name_,
+template void UsbCameraImpl::DeviceAddProperty(std::string_view name_,
tagCameraControlProperty tag,
IAMCameraControl* pProcAmp);
@@ -548,7 +570,8 @@
DeviceAddProperty(#val, CameraControl_##val, pCamControl);
void UsbCameraImpl::DeviceCacheProperties() {
- if (!m_sourceReader) return;
+ if (!m_sourceReader)
+ return;
IAMVideoProcAmp* pProcAmp = NULL;
@@ -645,7 +668,7 @@
} else {
// Read current raw value and set percentage from it
if (!rawProp->DeviceGet(lock, pProcAmp))
- SWARNING("failed to get property " << rawProp->name);
+ SWARNING("failed to get property {}", rawProp->name);
if (perProp) {
perProp->SetValue(RawToPercentage(*rawProp, rawProp->value));
@@ -656,7 +679,7 @@
// Set value on device if user-configured
if (rawProp->valueSet) {
if (!rawProp->DeviceSet(lock, pProcAmp))
- SWARNING("failed to set property " << rawProp->name);
+ SWARNING("failed to set property {}", rawProp->name);
}
// Update pointers since we released the lock
@@ -696,7 +719,8 @@
}
NotifyPropertyCreated(*rawIndex, *rawPropPtr);
- if (perPropPtr && perIndex) NotifyPropertyCreated(*perIndex, *perPropPtr);
+ if (perPropPtr && perIndex)
+ NotifyPropertyCreated(*perIndex, *perPropPtr);
}
CS_StatusValue UsbCameraImpl::DeviceProcessCommand(
@@ -739,11 +763,12 @@
bool setString = (msg.kind == Message::kCmdSetPropertyStr);
int property = msg.data[0];
int value = msg.data[1];
- wpi::StringRef valueStr = msg.dataStr;
+ std::string_view valueStr = msg.dataStr;
// Look up
auto prop = static_cast<UsbCameraProperty*>(GetProperty(property));
- if (!prop) return CS_INVALID_PROPERTY;
+ if (!prop)
+ return CS_INVALID_PROPERTY;
// If setting before we get, guess initial type based on set
if (prop->propKind == CS_PROP_NONE) {
@@ -774,7 +799,8 @@
// Actually set the new value on the device (if possible)
if (!prop->device) {
- if (prop->id == kPropConnectVerboseId) m_connectVerbose = value;
+ if (prop->id == kPropConnectVerboseId)
+ m_connectVerbose = value;
} else {
if (!prop->DeviceSet(lock, m_sourceReader.Get())) {
return CS_PROPERTY_WRITE_FAILED;
@@ -858,8 +884,12 @@
}
bool UsbCameraImpl::DeviceStreamOn() {
- if (m_streaming) return false;
- if (!m_deviceValid) return false;
+ if (m_streaming) {
+ return false;
+ }
+ if (!m_deviceValid) {
+ return false;
+ }
m_streaming = true;
m_sourceReader->ReadSample(MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0, NULL, NULL,
NULL, NULL);
@@ -872,9 +902,11 @@
}
void UsbCameraImpl::DeviceCacheMode() {
- if (!m_sourceReader) return;
+ if (!m_sourceReader)
+ return;
- if (m_windowsVideoModes.size() == 0) return;
+ if (m_windowsVideoModes.size() == 0)
+ return;
if (!m_currentMode) {
// First, see if our set mode is valid
@@ -939,7 +971,8 @@
}
void UsbCameraImpl::DeviceCacheVideoModes() {
- if (!m_sourceReader) return;
+ if (!m_sourceReader)
+ return;
std::vector<VideoMode> modes;
m_windowsVideoModes.clear();
@@ -990,23 +1023,21 @@
m_notifier.NotifySource(*this, CS_SOURCE_VIDEOMODES_UPDATED);
}
-static void ParseVidAndPid(wpi::StringRef path, int* pid, int* vid) {
- auto vidIndex = path.find_lower("vid_");
- auto pidIndex = path.find_lower("pid_");
+static void ParseVidAndPid(std::string_view path, int* pid, int* vid) {
+ auto vidIndex = wpi::find_lower(path, "vid_");
+ auto pidIndex = wpi::find_lower(path, "pid_");
- if (vidIndex != wpi::StringRef::npos) {
- auto vidSlice = path.slice(vidIndex + 4, vidIndex + 8);
- uint16_t val = 0;
- if (!vidSlice.getAsInteger(16, val)) {
- *vid = val;
+ if (vidIndex != std::string_view::npos) {
+ auto vidSlice = wpi::slice(path, vidIndex + 4, vidIndex + 8);
+ if (auto v = wpi::parse_integer<uint16_t>(vidSlice, 16)) {
+ *vid = v.value();
}
}
- if (pidIndex != wpi::StringRef::npos) {
- auto pidSlice = path.slice(pidIndex + 4, pidIndex + 8);
- uint16_t val = 0;
- if (!pidSlice.getAsInteger(16, val)) {
- *pid = val;
+ if (pidIndex != std::string_view::npos) {
+ auto pidSlice = wpi::slice(path, pidIndex + 4, pidIndex + 8);
+ if (auto v = wpi::parse_integer<uint16_t>(pidSlice, 16)) {
+ *pid = v.value();
}
}
}
@@ -1080,7 +1111,7 @@
return retval;
}
-CS_Source CreateUsbCameraDev(const wpi::Twine& name, int dev,
+CS_Source CreateUsbCameraDev(std::string_view name, int dev,
CS_Status* status) {
// First check if device exists
auto devices = cs::EnumerateUsbCameras(status);
@@ -1093,7 +1124,7 @@
return inst.CreateSource(CS_SOURCE_USB, source);
}
-CS_Source CreateUsbCameraPath(const wpi::Twine& name, const wpi::Twine& path,
+CS_Source CreateUsbCameraPath(std::string_view name, std::string_view path,
CS_Status* status) {
auto& inst = Instance::GetInstance();
auto source = std::make_shared<UsbCameraImpl>(
@@ -1101,7 +1132,7 @@
return inst.CreateSource(CS_SOURCE_USB, source);
}
-void SetUsbCameraPath(CS_Source source, const wpi::Twine& path,
+void SetUsbCameraPath(CS_Source source, std::string_view path,
CS_Status* status) {
auto data = Instance::GetInstance().GetSource(source);
if (!data || data->kind != CS_SOURCE_USB) {
diff --git a/cscore/src/main/native/windows/UsbCameraImpl.h b/cscore/src/main/native/windows/UsbCameraImpl.h
index 60a3080..ea6c104 100644
--- a/cscore/src/main/native/windows/UsbCameraImpl.h
+++ b/cscore/src/main/native/windows/UsbCameraImpl.h
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2018-2020 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#ifndef CSCORE_USBCAMERAIMPL_H_
#define CSCORE_USBCAMERAIMPL_H_
@@ -19,14 +16,13 @@
#include <atomic>
#include <memory>
#include <string>
+#include <string_view>
#include <thread>
#include <utility>
#include <vector>
#include <Dbt.h>
-#include <wpi/STLExtras.h>
#include <wpi/SmallVector.h>
-#include <wpi/Twine.h>
#include <wpi/condition_variable.h>
#include <wpi/mutex.h>
#include <wpi/raw_istream.h>
@@ -43,17 +39,17 @@
class UsbCameraImpl : public SourceImpl,
public std::enable_shared_from_this<UsbCameraImpl> {
public:
- UsbCameraImpl(const wpi::Twine& name, wpi::Logger& logger, Notifier& notifier,
- Telemetry& telemetry, const wpi::Twine& path);
- UsbCameraImpl(const wpi::Twine& name, wpi::Logger& logger, Notifier& notifier,
+ UsbCameraImpl(std::string_view name, wpi::Logger& logger, Notifier& notifier,
+ Telemetry& telemetry, std::string_view path);
+ UsbCameraImpl(std::string_view name, wpi::Logger& logger, Notifier& notifier,
Telemetry& telemetry, int deviceId);
~UsbCameraImpl() override;
- void Start();
+ void Start() override;
// Property functions
void SetProperty(int property, int value, CS_Status* status) override;
- void SetStringProperty(int property, const wpi::Twine& value,
+ void SetStringProperty(int property, std::string_view value,
CS_Status* status) override;
// Standard common camera properties
@@ -78,7 +74,7 @@
void ProcessFrame(IMFSample* sample, const VideoMode& mode);
void PostRequestNewFrame();
- void SetPath(const wpi::Twine& path, CS_Status* status);
+ void SetPath(std::string_view path, CS_Status* status);
std::string GetPath() const;
// Messages passed to/from camera thread
@@ -110,7 +106,7 @@
protected:
std::unique_ptr<PropertyImpl> CreateEmptyProperty(
- const wpi::Twine& name) const override;
+ std::string_view name) const override;
// Cache properties. Immediately successful if properties are already cached.
// If they are not, tries to connect to the camera to do so; returns false and
@@ -135,7 +131,7 @@
void DeviceCacheProperties();
void DeviceCacheVideoModes();
template <typename TagProperty, typename IAM>
- void DeviceAddProperty(const wpi::Twine& name_, TagProperty tag,
+ void DeviceAddProperty(std::string_view name_, TagProperty tag,
IAM* pProcAmp);
ComPtr<IMFMediaType> DeviceCheckModeValid(const VideoMode& toCheck);
diff --git a/cscore/src/main/native/windows/UsbCameraListener.cpp b/cscore/src/main/native/windows/UsbCameraListener.cpp
new file mode 100644
index 0000000..be33771
--- /dev/null
+++ b/cscore/src/main/native/windows/UsbCameraListener.cpp
@@ -0,0 +1,72 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+#include "UsbCameraListener.h"
+
+#include "Notifier.h"
+#include "WindowsMessagePump.h"
+
+#include <dbt.h> // NOLINT(build/include_order)
+
+#define IDT_TIMER1 1001
+
+using namespace cs;
+
+class UsbCameraListener::Impl {
+ public:
+ explicit Impl(Notifier& notifier) : m_notifier{notifier} {}
+
+ void Start() {
+ m_messagePump = std::make_unique<WindowsMessagePump>(
+ [this](HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam) {
+ return this->PumpMain(hwnd, uiMsg, wParam, lParam);
+ });
+ }
+
+ void Stop() { m_messagePump = nullptr; }
+
+ LRESULT PumpMain(HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam) {
+ switch (uiMsg) {
+ case WM_CLOSE:
+ KillTimer(hwnd, IDT_TIMER1);
+ break;
+ case WM_TIMER:
+ if (wParam == IDT_TIMER1) {
+ KillTimer(hwnd, IDT_TIMER1);
+ m_notifier.NotifyUsbCamerasChanged();
+ }
+ break;
+ case WM_DEVICECHANGE:
+ PDEV_BROADCAST_HDR parameter =
+ reinterpret_cast<PDEV_BROADCAST_HDR>(lParam);
+ if (wParam == DBT_DEVICEARRIVAL &&
+ parameter->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
+ SetTimer(hwnd, IDT_TIMER1, 200, nullptr);
+ } else if (wParam == DBT_DEVICEREMOVECOMPLETE &&
+ parameter->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
+ SetTimer(hwnd, IDT_TIMER1, 200, nullptr);
+ }
+ break;
+ }
+ return 0;
+ }
+
+ Notifier& m_notifier;
+ std::unique_ptr<cs::WindowsMessagePump> m_messagePump;
+};
+
+UsbCameraListener::UsbCameraListener(wpi::Logger& logger, Notifier& notifier)
+ : m_impl{std::make_unique<Impl>(notifier)} {}
+
+UsbCameraListener::~UsbCameraListener() {
+ Stop();
+}
+
+void UsbCameraListener::Start() {
+ m_impl->Start();
+}
+
+void UsbCameraListener::Stop() {
+ m_impl->Stop();
+}
diff --git a/cscore/src/main/native/windows/UsbCameraProperty.cpp b/cscore/src/main/native/windows/UsbCameraProperty.cpp
index ae22436..5ddeebf 100644
--- a/cscore/src/main/native/windows/UsbCameraProperty.cpp
+++ b/cscore/src/main/native/windows/UsbCameraProperty.cpp
@@ -1,20 +1,19 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#include "UsbCameraProperty.h"
+#include <fmt/format.h>
+
#include "ComPtr.h"
using namespace cs;
-UsbCameraProperty::UsbCameraProperty(const wpi::Twine& name_,
+UsbCameraProperty::UsbCameraProperty(std::string_view name_,
tagVideoProcAmpProperty tag, bool autoProp,
IAMVideoProcAmp* pProcAmp, bool* isValid)
- : PropertyImpl{autoProp ? name_ + "_auto" : name_} {
+ : PropertyImpl{autoProp ? fmt::format("{}_auto", name_) : name_} {
this->tagVideoProc = tag;
this->isControlProperty = false;
this->isAutoProp = autoProp;
@@ -41,7 +40,8 @@
bool UsbCameraProperty::DeviceGet(std::unique_lock<wpi::mutex>& lock,
IAMVideoProcAmp* pProcAmp) {
- if (!pProcAmp) return true;
+ if (!pProcAmp)
+ return true;
lock.unlock();
long newValue = 0, paramFlag = 0; // NOLINT(runtime/int)
@@ -60,7 +60,8 @@
bool UsbCameraProperty::DeviceSet(std::unique_lock<wpi::mutex>& lock,
IAMVideoProcAmp* pProcAmp,
int newValue) const {
- if (!pProcAmp) return true;
+ if (!pProcAmp)
+ return true;
lock.unlock();
if (SUCCEEDED(
@@ -72,11 +73,11 @@
return false;
}
-UsbCameraProperty::UsbCameraProperty(const wpi::Twine& name_,
+UsbCameraProperty::UsbCameraProperty(std::string_view name_,
tagCameraControlProperty tag,
bool autoProp, IAMCameraControl* pProcAmp,
bool* isValid)
- : PropertyImpl{autoProp ? name_ + "_auto" : name_} {
+ : PropertyImpl{autoProp ? fmt::format("{}_auto", name_) : name_} {
this->tagCameraControl = tag;
this->isControlProperty = true;
this->isAutoProp = autoProp;
@@ -103,7 +104,8 @@
bool UsbCameraProperty::DeviceGet(std::unique_lock<wpi::mutex>& lock,
IAMCameraControl* pProcAmp) {
- if (!pProcAmp) return true;
+ if (!pProcAmp)
+ return true;
lock.unlock();
long newValue = 0, paramFlag = 0; // NOLINT(runtime/int)
@@ -122,7 +124,8 @@
bool UsbCameraProperty::DeviceSet(std::unique_lock<wpi::mutex>& lock,
IAMCameraControl* pProcAmp,
int newValue) const {
- if (!pProcAmp) return true;
+ if (!pProcAmp)
+ return true;
lock.unlock();
if (SUCCEEDED(pProcAmp->Set(tagCameraControl, newValue,
@@ -136,7 +139,8 @@
bool UsbCameraProperty::DeviceGet(std::unique_lock<wpi::mutex>& lock,
IMFSourceReader* sourceReader) {
- if (!sourceReader) return true;
+ if (!sourceReader)
+ return true;
if (isControlProperty) {
ComPtr<IAMCameraControl> pProcAmp;
@@ -165,7 +169,8 @@
bool UsbCameraProperty::DeviceSet(std::unique_lock<wpi::mutex>& lock,
IMFSourceReader* sourceReader,
int newValue) const {
- if (!sourceReader) return true;
+ if (!sourceReader)
+ return true;
if (isControlProperty) {
ComPtr<IAMCameraControl> pProcAmp;
diff --git a/cscore/src/main/native/windows/UsbCameraProperty.h b/cscore/src/main/native/windows/UsbCameraProperty.h
index 11888e9..03cd375 100644
--- a/cscore/src/main/native/windows/UsbCameraProperty.h
+++ b/cscore/src/main/native/windows/UsbCameraProperty.h
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#pragma once
@@ -12,6 +9,7 @@
#include <mfreadwrite.h>
#include <memory>
+#include <string_view>
#include <Dshow.h>
#include <wpi/mutex.h>
@@ -24,19 +22,19 @@
class UsbCameraProperty : public PropertyImpl {
public:
UsbCameraProperty() = default;
- explicit UsbCameraProperty(const wpi::Twine& name_) : PropertyImpl{name_} {}
+ explicit UsbCameraProperty(std::string_view name_) : PropertyImpl{name_} {}
// Software property constructor
- UsbCameraProperty(const wpi::Twine& name_, unsigned id_,
- CS_PropertyKind kind_, int minimum_, int maximum_,
- int step_, int defaultValue_, int value_)
+ UsbCameraProperty(std::string_view name_, unsigned id_, CS_PropertyKind kind_,
+ int minimum_, int maximum_, int step_, int defaultValue_,
+ int value_)
: PropertyImpl(name_, kind_, minimum_, maximum_, step_, defaultValue_,
value_),
device{false},
id{id_} {}
// Normalized property constructor
- UsbCameraProperty(const wpi::Twine& name_, int rawIndex_,
+ UsbCameraProperty(std::string_view name_, int rawIndex_,
const UsbCameraProperty& rawProp, int defaultValue_,
int value_)
: PropertyImpl(name_, rawProp.propKind, 1, defaultValue_, value_),
@@ -50,10 +48,10 @@
maximum = 100;
}
- UsbCameraProperty(const wpi::Twine& name_, tagVideoProcAmpProperty tag,
+ UsbCameraProperty(std::string_view name_, tagVideoProcAmpProperty tag,
bool autoProp, IAMVideoProcAmp* pProcAmp, bool* isValid);
- UsbCameraProperty(const wpi::Twine& name_, tagCameraControlProperty tag,
+ UsbCameraProperty(std::string_view name_, tagCameraControlProperty tag,
bool autoProp, IAMCameraControl* pProcAmp, bool* isValid);
bool DeviceGet(std::unique_lock<wpi::mutex>& lock,
diff --git a/cscore/src/main/native/windows/WindowsMessagePump.cpp b/cscore/src/main/native/windows/WindowsMessagePump.cpp
index 0206bd0..e0d78d7 100644
--- a/cscore/src/main/native/windows/WindowsMessagePump.cpp
+++ b/cscore/src/main/native/windows/WindowsMessagePump.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2018 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#include "WindowsMessagePump.h"
@@ -93,7 +90,7 @@
std::function<LRESULT(HWND, UINT, WPARAM, LPARAM)> callback) {
m_callback = callback;
auto handle = CreateEvent(NULL, true, false, NULL);
- m_mainThread = std::thread([=]() { ThreadMain(handle); });
+ m_mainThread = std::thread([=] { ThreadMain(handle); });
auto waitResult = WaitForSingleObject(handle, 1000);
if (waitResult == WAIT_OBJECT_0) {
CloseHandle(handle);
@@ -102,7 +99,8 @@
WindowsMessagePump::~WindowsMessagePump() {
auto res = SendMessage(hwnd, WM_CLOSE, NULL, NULL);
- if (m_mainThread.joinable()) m_mainThread.join();
+ if (m_mainThread.joinable())
+ m_mainThread.join();
}
void WindowsMessagePump::ThreadMain(HANDLE eventHandle) {
diff --git a/cscore/src/main/native/windows/WindowsMessagePump.h b/cscore/src/main/native/windows/WindowsMessagePump.h
index 4638e4e..97a3f2d 100644
--- a/cscore/src/main/native/windows/WindowsMessagePump.h
+++ b/cscore/src/main/native/windows/WindowsMessagePump.h
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2018 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#pragma once
@@ -15,7 +12,7 @@
namespace cs {
class WindowsMessagePump {
public:
- WindowsMessagePump(
+ explicit WindowsMessagePump(
std::function<LRESULT(HWND, UINT, WPARAM, LPARAM)> callback);
~WindowsMessagePump();
diff --git a/cscore/src/test/java/edu/wpi/cscore/JNITest.java b/cscore/src/test/java/edu/wpi/cscore/JNITest.java
deleted file mode 100644
index b3c1062..0000000
--- a/cscore/src/test/java/edu/wpi/cscore/JNITest.java
+++ /dev/null
@@ -1,18 +0,0 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2017-2018 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.junit.jupiter.api.Test;
-
-class JNITest {
- @Test
- void jniLinkTest() {
- // Test to verify that the JNI test link works correctly.
- CameraServerJNI.getHostname();
- }
-}
diff --git a/cscore/src/test/java/edu/wpi/first/cscore/JNITest.java b/cscore/src/test/java/edu/wpi/first/cscore/JNITest.java
new file mode 100644
index 0000000..40e2584
--- /dev/null
+++ b/cscore/src/test/java/edu/wpi/first/cscore/JNITest.java
@@ -0,0 +1,15 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+package edu.wpi.first.cscore;
+
+import org.junit.jupiter.api.Test;
+
+class JNITest {
+ @Test
+ void jniLinkTest() {
+ // Test to verify that the JNI test link works correctly.
+ CameraServerJNI.getHostname();
+ }
+}
diff --git a/cscore/src/test/java/edu/wpi/cscore/UsbCameraTest.java b/cscore/src/test/java/edu/wpi/first/cscore/UsbCameraTest.java
similarity index 67%
rename from cscore/src/test/java/edu/wpi/cscore/UsbCameraTest.java
rename to cscore/src/test/java/edu/wpi/first/cscore/UsbCameraTest.java
index bc7866d..f0a679f 100644
--- a/cscore/src/test/java/edu/wpi/cscore/UsbCameraTest.java
+++ b/cscore/src/test/java/edu/wpi/first/cscore/UsbCameraTest.java
@@ -1,31 +1,27 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2018-2020 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
-package edu.wpi.cscore;
+package edu.wpi.first.cscore;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import java.time.Duration;
import java.util.Arrays;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
-
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledOnOs;
import org.junit.jupiter.api.condition.OS;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
class UsbCameraTest {
@Nested
@EnabledOnOs(OS.LINUX)
- class ConnectVerbose {
+ static class ConnectVerbose {
@Test
void setConnectVerboseEnabledTest() {
try (UsbCamera camera = new UsbCamera("Nonexistant Camera", getNonexistentCameraDev())) {
@@ -34,7 +30,8 @@
CompletableFuture<String> result = new CompletableFuture<>();
CameraServerJNI.setLogger((level, file, line, message) -> result.complete(message), 20);
- assertTimeoutPreemptively(Duration.ofSeconds(5),
+ assertTimeoutPreemptively(
+ Duration.ofSeconds(5),
() -> assertTrue(result.get().contains("Connecting to USB camera on ")));
}
}
@@ -47,15 +44,16 @@
CompletableFuture<String> result = new CompletableFuture<>();
CameraServerJNI.setLogger((level, file, line, message) -> result.complete(message), 20);
- assertThrows(TimeoutException.class,
- () -> result.get(3, TimeUnit.SECONDS));
+ assertThrows(TimeoutException.class, () -> result.get(3, TimeUnit.SECONDS));
}
}
}
private static int getNonexistentCameraDev() {
return Arrays.stream(CameraServerJNI.enumerateUsbCameras())
- .mapToInt(info -> info.dev)
- .max().orElse(-1) + 20;
+ .mapToInt(info -> info.dev)
+ .max()
+ .orElse(-1)
+ + 20;
}
}
diff --git a/cscore/src/test/native/cpp/CameraSourceTest.cpp b/cscore/src/test/native/cpp/CameraSourceTest.cpp
index e09f5e6..4c860bf 100644
--- a/cscore/src/test/native/cpp/CameraSourceTest.cpp
+++ b/cscore/src/test/native/cpp/CameraSourceTest.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2015-2018 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#include "cscore.h"
#include "gtest/gtest.h"
@@ -12,11 +9,12 @@
class CameraSourceTest : public ::testing::Test {
protected:
- CameraSourceTest() {}
+ CameraSourceTest() = default;
};
TEST_F(CameraSourceTest, HTTPCamera) {
auto source = HttpCamera("axis", "http://localhost:8000");
+ cs::Shutdown();
}
} // namespace cs
diff --git a/cscore/src/test/native/cpp/main.cpp b/cscore/src/test/native/cpp/main.cpp
index 1e5ecf0..09072ee 100644
--- a/cscore/src/test/native/cpp/main.cpp
+++ b/cscore/src/test/native/cpp/main.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2015-2018 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. */
-/*----------------------------------------------------------------------------*/
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
#include "gtest/gtest.h"