GCC Code Coverage Report


Directory: ./
File: mediaoutput/V4L2Device.h
Date: 2026-10-29 08:11:58
Exec Total Coverage
Lines: 2 3 66.7%
Functions: 1 2 50.0%
Branches: 3 8 37.5%

Line Branch Exec Source
1 #pragma once
2 /*
3 * This file is part of the Falcon Player (FPP) and is Copyright (C)
4 * 2013-2026 by the Falcon Player Developers.
5 *
6 * The Falcon Player (FPP) is free software, and is covered under
7 * multiple Open Source licenses. Please see the included 'LICENSES'
8 * file for descriptions of what files are covered by each license.
9 *
10 * This source file is covered under the LGPL v2.1 as described in the
11 * included LICENSE.LGPL file.
12 */
13
14 #include <string>
15 #include <vector>
16
17 /**
18 * V4L2Device — direct V4L2 queries against a capture device, for the
19 * things GStreamer's v4l2src either can't express or gets wrong for us.
20 *
21 * Two jobs:
22 *
23 * 1. Anti-flicker / exposure controls. A camera lit by mains lighting
24 * bands or pulses unless its auto-exposure quantises exposure to whole
25 * half-cycles of the supply. That's V4L2_CID_POWER_LINE_FREQUENCY,
26 * and it's a device control, not something the pipeline can do
27 * downstream: no amount of videorate/videoscale fixes light that was
28 * already integrated wrong.
29 *
30 * Controls are addressed by numeric CID rather than by name through
31 * v4l2src's extra-controls property, because the names moved in
32 * Linux 6.x (exposure_auto -> auto_exposure, exposure_absolute ->
33 * exposure_time_absolute) and extra-controls only warns on a name it
34 * can't resolve. CIDs are stable ABI.
35 *
36 * 2. Capture mode enumeration, so the configured resolution/framerate can
37 * be pinned on the device instead of being quietly resampled after the
38 * fact. See SelectMode().
39 *
40 * Every entry point is a no-op returning failure on non-Linux builds.
41 */
42 namespace V4L2Device {
43
44 /// One discrete capture mode the device advertises.
45 struct Mode {
46 std::string fourcc; ///< e.g. "MJPG", "YUYV"
47 int width = 0;
48 int height = 0;
49 int fpsNum = 0; ///< framerate = fpsNum / fpsDen
50 int fpsDen = 1;
51
52 ✗ double fps() const { return fpsDen ? (double)fpsNum / fpsDen : 0.0; }
53 };
54
55 /// Requested device controls. -1 / "camera" means "leave the camera's own
56 /// setting alone" so an untouched config behaves exactly as it did before.
57 struct ControlSettings {
58 /// V4L2_CID_POWER_LINE_FREQUENCY: -1 leave, 0 disabled, 1 = 50Hz, 2 = 60Hz.
59 int powerLineFrequency = -1;
60
61 /// "camera" (leave), "auto", or "manual". Maps onto whichever
62 /// V4L2_CID_EXPOSURE_AUTO menu entries the device actually offers.
63 std::string exposureMode = "camera";
64
65 /// V4L2_CID_EXPOSURE_ABSOLUTE, in 100us units. Only applied when
66 /// exposureMode == "manual". -1 leaves the camera's value.
67 int exposureTime100us = -1;
68
69 /// V4L2_CID_EXPOSURE_AUTO_PRIORITY ("exposure_dynamic_framerate"):
70 /// -1 leave, 1 = let AE drop the framerate, 0 = hold the framerate.
71 /// Worth holding when chasing flicker — a variable frame interval
72 /// reintroduces beating against the light even once exposure is
73 /// quantised correctly.
74 int dynamicFramerate = -1;
75
76 129 bool AnyRequested() const {
77
3/6
✓ Branch 0 taken 129 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 129 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 129 times.
129 return powerLineFrequency >= 0 || exposureMode != "camera" || dynamicFramerate >= 0;
78 }
79 };
80
81 /// Apply `s` to `device`. Controls the device doesn't implement are
82 /// skipped, not treated as failure. `summary` gets a human-readable
83 /// "name=value" list of what actually landed, for the log.
84 /// Returns false only if the device could not be opened at all.
85 bool ApplyControls(const std::string& device, const ControlSettings& s, std::string& summary);
86
87 /// All discrete capture modes the device advertises. Empty if the device
88 /// can't be opened or enumerates nothing usable.
89 std::vector<Mode> EnumerateModes(const std::string& device);
90
91 /// Pick the mode to ask the device for, given what the config wants.
92 ///
93 /// Prefers an exact width/height/framerate match; failing that the
94 /// smallest mode that still covers the requested size (so videoscale
95 /// downscales rather than upscales), and among equals the one whose
96 /// framerate best covers the request. Returns false when `modes` is
97 /// empty, in which case the caller should not constrain the device at all.
98 bool SelectMode(const std::vector<Mode>& modes, int width, int height, int fps, Mode& out);
99
100 /// GStreamer caps for a mode, e.g. "image/jpeg,width=1280,height=720,framerate=30/1".
101 /// Empty string if the fourcc has no caps mapping we trust, in which case
102 /// the caller should leave the device unconstrained.
103 std::string ModeToCaps(const Mode& m);
104
105 } // namespace V4L2Device
106