-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMVMExtraSegment.cxx
137 lines (113 loc) · 5.65 KB
/
MVMExtraSegment.cxx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
//
// Created by Zhiping Jiang on 9/9/21.
//
#include "MVMExtraSegment.hxx"
IntelMVMParsedCSIHeader::IntelMVMParsedCSIHeader() {
memset(this, 0, sizeof(IntelMVMParsedCSIHeader));
}
bool IntelMVMParsedCSIHeader::operator==(const IntelMVMParsedCSIHeader &rhs) const {
return std::memcmp(this, &rhs, sizeof(IntelMVMParsedCSIHeader));
}
bool IntelMVMParsedCSIHeader::operator!=(const IntelMVMParsedCSIHeader &rhs) const {
return !(rhs == *this);
}
IntelRateNFlag IntelMVMParsedCSIHeader::getRateNFlagInterpretation() const {
return IntelRateNFlag(rateNflag);
}
void IntelMVMParsedCSIHeader::registerDefaultMVMHeaderInterpretation() {
auto fields = std::vector<DynamicContentField>{
DynamicContentField{
.fieldName = "IQDataSize",
.fieldType = DynamicContentFieldPrimitiveType::Uint32,
.fieldOffset = 0,
.arraySize = 1,
},
DynamicContentField{
.fieldName = "FTMClock",
.fieldType = DynamicContentFieldPrimitiveType::Uint32,
.fieldOffset = 8,
.arraySize = 1,
},
DynamicContentField{
.fieldName = "NumTones",
.fieldType = DynamicContentFieldPrimitiveType::Uint32,
.fieldOffset = 52,
.arraySize = 1,
},
DynamicContentField{
.fieldName = "RateNFlags",
.fieldType = DynamicContentFieldPrimitiveType::Uint32,
.fieldOffset = 92,
.arraySize = 1,
},
};
/// Compensate for the leading 2-byte header length
for(auto & field: fields)
field.fieldOffset += 2;
DynamicContentTypeDictionary::getInstance()->registerType(DynamicContentType{"MVMExtra", 1, fields});
}
static auto v1Parser = [](const uint8_t *buffer, const uint32_t bufferLength) -> IntelMVMExtraInfo {
uint32_t pos = 0;
auto extra = IntelMVMExtraInfo();
extra.CSIHeaderLength = *reinterpret_cast<const uint16_t *>(buffer + pos);
pos += 2;
if (bufferLength - pos < extra.CSIHeaderLength)
throw std::runtime_error("MVMExtraSegment v1Parser cannot parse the segment with insufficient buffer length.");
extra.parsedHeader = *reinterpret_cast<const IntelMVMParsedCSIHeader *>(buffer + pos);
pos += sizeof(IntelMVMParsedCSIHeader);
MVMExtraSegment::manipulateHeader(extra.parsedHeader);
std::copy_n(reinterpret_cast<uint8_t *>(&extra.parsedHeader), sizeof(IntelMVMParsedCSIHeader), std::back_inserter(extra.CSIHeader));
std::copy(buffer + pos, buffer + bufferLength, std::back_inserter(extra.CSIHeader));
if (false) {
IntelMVMParsedCSIHeader regeneratedInstance = *(IntelMVMParsedCSIHeader *) extra.CSIHeader.data();
if (extra.parsedHeader != regeneratedInstance)
throw std::runtime_error("failed to validate IntelMVMParsedCSIHeader parser.");
}
return extra;
};
std::vector<uint8_t> IntelMVMExtraInfo::toBuffer() const {
auto buffer = std::vector<uint8_t>(sizeof(CSIHeaderLength) + CSIHeader.size());
std::copy_n(reinterpret_cast<const uint8_t *>(&CSIHeaderLength), sizeof(CSIHeaderLength), buffer.begin());
std::copy_n(CSIHeader.cbegin(), CSIHeader.size(), buffer.begin() + sizeof(CSIHeaderLength));
return buffer;
}
std::map<uint16_t, std::function<IntelMVMExtraInfo(const uint8_t *, uint32_t)>> MVMExtraSegment::versionedSolutionMap = initializeSolutionMap();
std::map<uint16_t, std::function<IntelMVMExtraInfo(const uint8_t *, uint32_t)>> MVMExtraSegment::initializeSolutionMap() noexcept {
std::map<uint16_t, std::function<IntelMVMExtraInfo(const uint8_t *, uint32_t)>> map;
map.emplace(0x1U, v1Parser);
return map;
}
std::function<void(IntelMVMParsedCSIHeader &)> MVMExtraSegment::headerManipulator{nullptr};
MVMExtraSegment::MVMExtraSegment() : AbstractPicoScenesFrameSegment("MVMExtra", 0x1U) {}
MVMExtraSegment::MVMExtraSegment(const uint8_t *buffer, const uint32_t bufferLength) : AbstractPicoScenesFrameSegment(buffer, bufferLength) {
if (segmentName != "MVMExtra")
throw std::runtime_error("MVMExtraSegment cannot parse the segment named " + segmentName + ".");
if (!versionedSolutionMap.contains(segmentVersionId))
throw std::runtime_error("MVMExtraSegment cannot parse the segment with version v" + std::to_string(segmentVersionId) + ".");
mvmExtra = versionedSolutionMap.at(segmentVersionId)(segmentPayload.data(), segmentPayload.size());
setMvmExtra(mvmExtra);
}
std::string MVMExtraSegment::toString() const {
std::stringstream ss;
ss << segmentName + ":[";
ss << "hdr_len=" << mvmExtra.CSIHeaderLength << ", csi_len=" << mvmExtra.parsedHeader.iqDataSize << "B, num_tone=" << mvmExtra.parsedHeader.numTones << ", ftm_clock=" << std::dec << mvmExtra.parsedHeader.ftmClock << "]";
auto temp = ss.str();
return temp;
}
const IntelMVMExtraInfo &MVMExtraSegment::getMvmExtra() const {
return mvmExtra;
}
void MVMExtraSegment::manipulateHeader(IntelMVMParsedCSIHeader &header) {
if (headerManipulator)
headerManipulator(header);
}
void MVMExtraSegment::setHeaderManipulator(const std::function<void(IntelMVMParsedCSIHeader &)> &headerManipulator) {
static std::once_flag flag;
std::call_once(flag, [&] {
MVMExtraSegment::headerManipulator = headerManipulator == nullptr ? MVMExtraSegment::headerManipulator : headerManipulator; // this property can only be set once during the start
});
}
void MVMExtraSegment::setMvmExtra(const IntelMVMExtraInfo &mvmExtraV) {
mvmExtra = mvmExtraV;
setSegmentPayload(std::move(mvmExtra.toBuffer()));
}