GCC Code Coverage Report


Directory: ./
File: channeloutput/Matrix.cpp
Date: 2026-10-29 08:11:58
Exec Total Coverage
Lines: 42 45 93.3%
Functions: 5 5 100.0%
Branches: 27 48 56.2%

Line Branch Exec Source
1 /*
2 * This file is part of the Falcon Player (FPP) and is Copyright (C)
3 * 2013-2022 by the Falcon Player Developers.
4 *
5 * The Falcon Player (FPP) is free software, and is covered under
6 * multiple Open Source licenses. Please see the included 'LICENSES'
7 * file for descriptions of what files are covered by each license.
8 *
9 * This source file is covered under the LGPL v2.1 as described in the
10 * included LICENSE.LGPL file.
11 */
12
13 #include "fpp-pch.h"
14
15 #include "../log.h"
16
17 #include "../Sequence.h"
18 #include "Matrix.h"
19 #include <cstring> // memcpy -- needed directly for NOPCH builds
20
21 /*
22 *
23 */
24 118 Matrix::Matrix(int startChannel, int width, int height) :
25 118 m_startChannel(startChannel),
26 118 m_width(width),
27 118 m_height(height) {
28
1/2
✓ Branch 0 taken 118 times.
✗ Branch 1 not taken.
118 LogDebug(VB_CHANNELOUT, "New Matrix: %dx%d\n", width, height);
29
30
1/2
✓ Branch 0 taken 118 times.
✗ Branch 1 not taken.
118 m_buffer = new unsigned char[width * height * 3];
31
32 118 m_enableFlagOffset = startChannel + (width * height * 3);
33 118 }
34
35 /*
36 *
37 */
38 118 Matrix::~Matrix() {
39
1/2
✓ Branch 0 taken 118 times.
✗ Branch 1 not taken.
118 delete[] m_buffer;
40 118 }
41
42 /*
43 *
44 */
45 4 void Matrix::AddSubMatrix(int enabled, int startChannel, int width, int height,
46 int xOffset, int yOffset) {
47
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 LogDebug(VB_CHANNELOUT,
48 "New SubMatrix: %dx%d+%d+%d @ channel %d, enabled: %d\n",
49 width, height, xOffset, yOffset, startChannel, enabled);
50 // Every frame copies the sub-matrix into m_buffer row by row, from its
51 // own channels: one that does not fit inside the matrix overran the heap
52 // buffer, and channels outside the channel data read past it.
53
5/8
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
4 if (width <= 0 || height <= 0 || xOffset < 0 || yOffset < 0 ||
54
4/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
3 (int64_t)xOffset + width > m_width || (int64_t)yOffset + height > m_height ||
55
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 startChannel < 0 || (int64_t)startChannel + (int64_t)width * height * 3 > FPPD_MAX_CHANNELS) {
56
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 LogErr(VB_CHANNELOUT, "Ignoring sub-matrix %dx%d+%d+%d at channel %d: it does not fit the %dx%d matrix or the channel data\n",
57 width, height, xOffset, yOffset, startChannel + 1, m_width, m_height);
58 3 return;
59 }
60 SubMatrix newSub;
61
62 1 newSub.enabled = enabled;
63 1 newSub.startChannel = startChannel;
64 1 newSub.width = width;
65 1 newSub.height = height;
66 1 newSub.xOffset = xOffset;
67 1 newSub.yOffset = yOffset;
68
69
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 subMatrix.push_back(newSub);
70 }
71
72 /*
73 *
74 */
75 9 void Matrix::OverlaySubMatrix(unsigned char* channelData, int i) {
76
3/6
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 9 times.
9 if (i < 0 || i >= (int)subMatrix.size())
77 ✗ return;
78
79 // Check to see if this submatrix is enabled. The enable flags follow the
80 // matrix's own channels, so a matrix that ends at the top of the channel
81 // data has none.
82
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
9 if (!subMatrix[i].enabled &&
83 ✗ ((int64_t)m_enableFlagOffset + i >= FPPD_MAX_CHANNELS || !channelData[m_enableFlagOffset + i]))
84 ✗ return;
85
86 9 int startChannel = subMatrix[i].startChannel;
87 9 int xOffset = subMatrix[i].xOffset;
88 9 int yOffset = subMatrix[i].yOffset;
89
90 unsigned char* src;
91 unsigned char* dest;
92
93
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
18 for (int y = 0; y < subMatrix[i].height; y++) {
94 9 src = channelData + subMatrix[i].startChannel + (y * subMatrix[i].width * 3);
95 9 dest = m_buffer + ((y + subMatrix[i].yOffset) * m_width * 3) + (subMatrix[i].xOffset * 3);
96
97 9 memcpy(dest, src, subMatrix[i].width * 3);
98 }
99 }
100
101 /*
102 *
103 */
104 3253 void Matrix::OverlaySubMatrices(unsigned char* channelData) {
105
2/2
✓ Branch 0 taken 3244 times.
✓ Branch 1 taken 9 times.
3253 if (!subMatrix.size())
106 3244 return;
107
108 // Clear the matrix before applying submatrices
109 // bzero(m_buffer, m_width * m_height * 3);
110
111 // Instead, just populate our temp buffer with the contents of the matrix
112 9 memcpy(m_buffer, channelData + m_startChannel, m_width * m_height * 3);
113
114
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
18 for (int i = 0; i < subMatrix.size(); i++) {
115 9 OverlaySubMatrix(channelData, i);
116 }
117
118 9 memcpy(channelData + m_startChannel, m_buffer, m_width * m_height * 3);
119 }
120