| 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 "fpp-json.h" | ||
| 16 | |||
| 17 | #include "../../Warnings.h" | ||
| 18 | #include "../../log.h" | ||
| 19 | |||
| 20 | #include "FoldOutputProcessor.h" | ||
| 21 | |||
| 22 | 7 | FoldOutputProcessor::FoldOutputProcessor(const Json::Value& config) { | |
| 23 |
2/4✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
|
7 | description = config["description"].asString(); |
| 24 |
2/4✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
|
7 | active = config["active"].asInt() ? true : false; |
| 25 |
2/4✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
|
7 | sourceChannel = config["source"].asInt() - 1; |
| 26 |
2/4✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
|
7 | count = config["count"].asInt(); |
| 27 |
2/4✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
|
7 | node = config["node"].asInt(); // By channel, RGB Pixel, RGBW Pixel |
| 28 | |||
| 29 | // node is the UI selector, nodesize the channels per node it selects. All of | ||
| 30 | // the fold index math below is in nodesize, never in the raw selector. | ||
| 31 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 4 times.
|
7 | if (node == 1) { |
| 32 | 3 | nodesize = 3; | |
| 33 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | } else if (node == 2) { |
| 34 | ✗ | nodesize = 4; | |
| 35 | } else { | ||
| 36 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
|
4 | if (node != 0) { |
| 37 | 1 | std::string warning = "Fold output processor has an unknown node option (" + | |
| 38 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
2 | std::to_string(node) + "), falling back to By Channel"; |
| 39 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | LogWarn(VB_CHANNELOUT, "%s\n", warning.c_str()); |
| 40 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | WarningHolder::AddWarning(warning); |
| 41 | 1 | node = 0; | |
| 42 | 1 | } | |
| 43 | 4 | nodesize = 1; | |
| 44 | } | ||
| 45 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | if (count < 0) { |
| 46 | ✗ | std::string warning = "Fold output processor has a negative channel count (" + | |
| 47 | ✗ | std::to_string(count) + "), disabling it"; | |
| 48 | ✗ | LogWarn(VB_CHANNELOUT, "%s\n", warning.c_str()); | |
| 49 | ✗ | WarningHolder::AddWarning(warning); | |
| 50 | ✗ | count = 0; | |
| 51 | ✗ | } | |
| 52 | // "source" is the 1-based channel the UI shows, so anything below 1 puts | ||
| 53 | // sourceChannel before the start of the buffer ProcessData indexes. | ||
| 54 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3 times.
|
7 | if (sourceChannel < 0) { |
| 55 | 4 | std::string warning = "Fold output processor has an invalid start channel (" + | |
| 56 |
4/8✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
|
8 | std::to_string(config["source"].asInt()) + "), disabling it"; |
| 57 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | LogWarn(VB_CHANNELOUT, "%s\n", warning.c_str()); |
| 58 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | WarningHolder::AddWarning(warning); |
| 59 | 4 | sourceChannel = 0; | |
| 60 | 4 | count = 0; | |
| 61 | 4 | } | |
| 62 | // sourceChannel + count is reported in an int: keep both where it can't | ||
| 63 | // overflow into the inverted, "nothing to do" range rangeIsValid() passes. | ||
| 64 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | if (sourceChannel > (int)FPPD_MAX_CHANNELS) { |
| 65 | ✗ | sourceChannel = FPPD_MAX_CHANNELS; | |
| 66 | } | ||
| 67 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | if (count > (int)FPPD_MAX_CHANNELS + 1) { |
| 68 | ✗ | count = FPPD_MAX_CHANNELS + 1; | |
| 69 | } | ||
| 70 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | LogInfo(VB_CHANNELOUT, "Fold: channels: %d-%d, node size: %d\n", |
| 71 | sourceChannel, sourceChannel + count, nodesize); | ||
| 72 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | if (count % nodesize != 0) { |
| 73 | ✗ | LogWarn(VB_CHANNELOUT, | |
| 74 | "Channel count (%d) is not a multiple of the node size " | ||
| 75 | "(%d channels/node), the dangling channels will be ignored\n", | ||
| 76 | count, nodesize); | ||
| 77 | } | ||
| 78 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | tempBuffer.resize(count); |
| 79 | 7 | } | |
| 80 | |||
| 81 | ✗ | FoldOutputProcessor::FoldOutputProcessor(int src, int c, int n) { | |
| 82 | ✗ | active = true; | |
| 83 | ✗ | sourceChannel = src; | |
| 84 | ✗ | count = c < 0 ? 0 : c; | |
| 85 | ✗ | nodesize = n > 0 ? n : 1; | |
| 86 | ✗ | node = nodesize == 4 ? 2 : (nodesize == 3 ? 1 : 0); | |
| 87 | ✗ | tempBuffer.resize(count); | |
| 88 | ✗ | } | |
| 89 | |||
| 90 | ✗ | FoldOutputProcessor::~FoldOutputProcessor() { | |
| 91 | ✗ | } | |
| 92 | 14 | void FoldOutputProcessor::GetRequiredChannelRanges(const std::function<void(int, int)>& addRange) { | |
| 93 | 14 | addRange(sourceChannel, sourceChannel + count); | |
| 94 | 14 | } | |
| 95 | |||
| 96 | 115 | void FoldOutputProcessor::ProcessData(unsigned char* channelData) const { | |
| 97 | 115 | size_t len = count / nodesize; // Number of whole nodes; trailing channels are left alone | |
| 98 |
2/2✓ Branch 0 taken 56 times.
✓ Branch 1 taken 59 times.
|
115 | if (len == 0) { |
| 99 | 56 | return; | |
| 100 | } | ||
| 101 | // The fold reads every source node and writes it elsewhere in the same span, | ||
| 102 | // so the pre-fold values have to be snapshotted first. | ||
| 103 | 59 | memcpy(tempBuffer.data(), channelData + sourceChannel, count); | |
| 104 |
2/2✓ Branch 0 taken 1140 times.
✓ Branch 1 taken 59 times.
|
1199 | for (unsigned int node = 0; node < len; ++node) { |
| 105 | 2280 | memcpy( | |
| 106 | 2280 | channelData + sourceChannel + | |
| 107 |
0/2✗ Branch 0 not taken.
✗ Branch 1 not taken.
|
1140 | (node % 2 ? len - node / 2 - 1 : node / 2) * nodesize, |
| 108 |
2/2✓ Branch 0 taken 570 times.
✓ Branch 1 taken 570 times.
|
1140 | tempBuffer.data() + node * nodesize, |
| 109 | 1140 | nodesize); | |
| 110 | } | ||
| 111 | } | ||
| 112 |