Branch data Line data Source code
1 : : /*
2 : : * Copyright (C) 2026 by Thun Lu. All rights reserved.
3 : : * Author: Thun Lu <thun.lu@zohomail.cn>
4 : : * Repo: https://github.com/thun-res/vlink
5 : : * _ __ __ _ __
6 : : * | | / / / / (_) ____ / /__
7 : : * | | / / / / / / / __ \ / //_/
8 : : * | |/ / / /___ / / / / / / / ,<
9 : : * |___/ /_____/ /_/ /_/ /_/ /_/|_|
10 : : *
11 : : * Licensed under the Apache License, Version 2.0 (the "License");
12 : : * you may not use this file except in compliance with the License.
13 : : * You may obtain a copy of the License at
14 : : *
15 : : * http://www.apache.org/licenses/LICENSE-2.0
16 : : *
17 : : * Unless required by applicable law or agreed to in writing, software
18 : : * distributed under the License is distributed on an "AS IS" BASIS,
19 : : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 : : * See the License for the specific language governing permissions and
21 : : * limitations under the License.
22 : : */
23 : :
24 : : #include "./zerocopy/camera_frame.h"
25 : :
26 : : #include <cstdint>
27 : :
28 : : namespace vlink {
29 : :
30 : : namespace zerocopy {
31 : :
32 : : // CameraFrame
33 : 75 : CameraFrame::CameraFrame() noexcept {
34 : : #if defined(__arm__) || defined(__x86__) || defined(__i386__)
35 : : #ifndef __ANDROID__
36 : : #warning "[CameraFrame] No support for 32-bit architecture."
37 : : #endif
38 : : #else
39 : : static_assert(sizeof(CameraFrame) == 80, "Sizeof must be 80 bytes.");
40 : : #endif
41 : 75 : }
42 : :
43 : 77 : CameraFrame::~CameraFrame() noexcept {
44 [ + + + - : 77 : if (is_owner_ && data_ && size_ != 0) {
+ - ]
45 : 38 : Bytes::bytes_free(data_, size_);
46 : : }
47 : 77 : }
48 : :
49 : 1 : CameraFrame::CameraFrame(const CameraFrame& target) noexcept { deep_copy(target); }
50 : :
51 : 1 : CameraFrame::CameraFrame(CameraFrame&& target) noexcept { move_copy(target); }
52 : :
53 : 1 : CameraFrame& CameraFrame::operator=(const CameraFrame& target) noexcept {
54 [ - + ]: 1 : if VUNLIKELY (this == &target) {
55 : 0 : return *this;
56 : : }
57 : :
58 : 1 : deep_copy(target);
59 : :
60 : 1 : return *this;
61 : : }
62 : :
63 : 1 : CameraFrame& CameraFrame::operator=(CameraFrame&& target) noexcept {
64 [ - + ]: 1 : if VUNLIKELY (this == &target) {
65 : 0 : return *this;
66 : : }
67 : :
68 : 1 : move_copy(target);
69 : :
70 : 1 : return *this;
71 : : }
72 : :
73 : 11 : bool CameraFrame::operator<<(const Bytes& bytes) noexcept {
74 : : static constexpr size_t kMagicNumberBeginSize = sizeof(kMagicNumberBegin);
75 : : static constexpr size_t kVersionSize = sizeof(kWireVersion);
76 : : // static constexpr size_t kMagicNumberEndSize = sizeof(kMagicNumberEnd);
77 : :
78 [ + + ]: 11 : if VUNLIKELY (bytes.empty()) {
79 : 1 : return false;
80 : : }
81 : :
82 [ + + ]: 10 : if VUNLIKELY (!check_valid(bytes)) {
83 : 2 : return false;
84 : : }
85 : :
86 : 8 : uint32_t wire_version = 0;
87 : 8 : std::memcpy(&wire_version, bytes.data() + kMagicNumberBeginSize, kVersionSize);
88 : :
89 [ - + ]: 8 : if VUNLIKELY (version_major(wire_version) != version_major(kWireVersion)) {
90 : 0 : return false;
91 : : }
92 : :
93 [ + + + - : 8 : if (is_owner_ && data_ && size_ != 0) {
+ - ]
94 : 1 : Bytes::bytes_free(data_, size_);
95 : : }
96 : :
97 : : #if defined(__GNUC__) && !defined(__clang__)
98 : : #pragma GCC diagnostic push
99 : : #pragma GCC diagnostic ignored "-Wclass-memaccess"
100 : : #if __GNUC__ >= 11
101 : : #pragma GCC diagnostic ignored "-Wstringop-overread"
102 : : #endif
103 : : #endif
104 : :
105 : 8 : auto* target_ptr = reinterpret_cast<uint8_t*>(this);
106 : :
107 : 8 : std::memcpy(target_ptr, bytes.data() + kMagicNumberBeginSize + kVersionSize, sizeof(CameraFrame));
108 : :
109 : : #if defined(__GNUC__) && !defined(__clang__)
110 : : #pragma GCC diagnostic pop
111 : : #endif
112 : :
113 : 8 : data_ = const_cast<uint8_t*>(bytes.data() + kMagicNumberBeginSize + kVersionSize + sizeof(CameraFrame));
114 : 8 : is_owner_ = false;
115 : :
116 [ + + ]: 8 : if VUNLIKELY (bytes.size() != get_serialized_size()) {
117 : 1 : clear();
118 : 1 : return false;
119 : : }
120 : :
121 : 7 : return true;
122 : : }
123 : :
124 : 11 : bool CameraFrame::operator>>(Bytes& bytes) const noexcept {
125 : : static constexpr size_t kMagicNumberBeginSize = sizeof(kMagicNumberBegin);
126 : : static constexpr size_t kVersionSize = sizeof(kWireVersion);
127 : : static constexpr size_t kMagicNumberEndSize = sizeof(kMagicNumberEnd);
128 : :
129 [ + + - + : 11 : if (bytes.empty() || bytes.size() != get_serialized_size()) {
+ + ]
130 : 9 : bytes = Bytes::create(get_serialized_size());
131 : : }
132 : :
133 : 11 : std::memcpy(bytes.data(), &kMagicNumberBegin, kMagicNumberBeginSize);
134 : :
135 : 11 : std::memcpy(bytes.data() + kMagicNumberBeginSize, &kWireVersion, kVersionSize);
136 : :
137 : : // NOLINTNEXTLINE(bugprone-undefined-memory-manipulation)
138 : 11 : std::memcpy(bytes.data() + kMagicNumberBeginSize + kVersionSize, this, sizeof(CameraFrame));
139 : :
140 [ + + + - : 11 : if VLIKELY (data_ != nullptr && size_ != 0) {
+ + ]
141 : 10 : std::memcpy(bytes.data() + kMagicNumberBeginSize + kVersionSize + sizeof(CameraFrame), data_, size_);
142 : : }
143 : :
144 : 11 : std::memcpy(bytes.data() + kMagicNumberBeginSize + kVersionSize + sizeof(CameraFrame) + size_, &kMagicNumberEnd,
145 : : kMagicNumberEndSize);
146 : :
147 : 11 : return true;
148 : : }
149 : :
150 : 17 : bool CameraFrame::check_valid(const Bytes& bytes) noexcept {
151 : : static constexpr size_t kMagicNumberBeginSize = sizeof(kMagicNumberBegin);
152 : : static constexpr size_t kVersionSize = sizeof(kWireVersion);
153 : : static constexpr size_t kMagicNumberEndSize = sizeof(kMagicNumberEnd);
154 : :
155 [ + + ]: 17 : if VUNLIKELY (bytes.size() < kMagicNumberBeginSize + kVersionSize + sizeof(CameraFrame) + kMagicNumberEndSize) {
156 : 2 : return false;
157 : : }
158 : :
159 : 15 : uint32_t check_magic = 0;
160 : :
161 : 15 : std::memcpy(&check_magic, bytes.begin(), kMagicNumberBeginSize);
162 : :
163 [ + + ]: 15 : if VUNLIKELY (check_magic != kMagicNumberBegin) {
164 : 1 : return false;
165 : : }
166 : :
167 : 14 : uint32_t wire_version = 0;
168 : 14 : std::memcpy(&wire_version, bytes.data() + kMagicNumberBeginSize, kVersionSize);
169 : :
170 [ + + ]: 14 : if VUNLIKELY (version_major(wire_version) != version_major(kWireVersion)) {
171 : 2 : return false;
172 : : }
173 : :
174 : 12 : std::memcpy(&check_magic, bytes.end() - kMagicNumberEndSize, kMagicNumberEndSize);
175 : :
176 [ + + ]: 12 : if VUNLIKELY (check_magic != kMagicNumberEnd) {
177 : 1 : return false;
178 : : }
179 : :
180 : 11 : return true;
181 : : }
182 : :
183 : 24 : size_t CameraFrame::get_serialized_size() const noexcept {
184 : : static constexpr size_t kMagicNumberBeginSize = sizeof(kMagicNumberBegin);
185 : : static constexpr size_t kVersionSize = sizeof(kWireVersion);
186 : : static constexpr size_t kMagicNumberEndSize = sizeof(kMagicNumberEnd);
187 : :
188 : 24 : return kMagicNumberBeginSize + kVersionSize + sizeof(CameraFrame) + size_ + kMagicNumberEndSize;
189 : : }
190 : :
191 [ + + + - ]: 13 : bool CameraFrame::is_valid() const noexcept { return data_ != nullptr && size_ != 0; }
192 : :
193 : 13 : bool CameraFrame::shallow_copy(const CameraFrame& target) noexcept {
194 [ + + ]: 13 : if VUNLIKELY (this == &target) {
195 : 2 : return false;
196 : : }
197 : :
198 [ - + - - : 11 : if (is_owner_ && data_ && size_ != 0) {
- - ]
199 : 0 : Bytes::bytes_free(data_, size_);
200 : : }
201 : :
202 : 11 : header = target.header;
203 : :
204 : 11 : channel_ = target.channel_;
205 : 11 : height_ = target.height_;
206 : 11 : width_ = target.width_;
207 : 11 : freq_ = target.freq_;
208 : 11 : format_ = target.format_;
209 : 11 : stream_ = target.stream_;
210 : 11 : reserved_buf_ = target.reserved_buf_;
211 : 11 : is_owner_ = false;
212 : 11 : data_ = target.data_;
213 : 11 : size_ = target.size_;
214 : :
215 : 11 : return true;
216 : : }
217 : :
218 : 9 : bool CameraFrame::deep_copy(const CameraFrame& target) noexcept {
219 [ + + + - : 9 : if VLIKELY (data_ && is_owner_ && target.data_ && size_ != 0 && size_ == target.size_) {
+ + + - +
+ + - + +
+ - + + ]
220 [ + + ]: 2 : if VUNLIKELY (this == &target) {
221 : 1 : return false;
222 : : }
223 : :
224 : 1 : header = target.header;
225 : :
226 : 1 : channel_ = target.channel_;
227 : 1 : height_ = target.height_;
228 : 1 : width_ = target.width_;
229 : 1 : freq_ = target.freq_;
230 : 1 : format_ = target.format_;
231 : 1 : stream_ = target.stream_;
232 : 1 : reserved_buf_ = target.reserved_buf_;
233 : :
234 : 1 : std::memcpy(data_, target.data_, size_);
235 : :
236 : 1 : return true;
237 : : }
238 : :
239 [ - + ]: 7 : if VUNLIKELY (!shallow_copy(target)) {
240 : 0 : return false;
241 : : }
242 : :
243 [ + - + - ]: 7 : if (data_ && size_ != 0) {
244 : 7 : data_ = Bytes::bytes_malloc(size_);
245 : :
246 : 7 : std::memcpy(data_, target.data_, size_);
247 : :
248 : 7 : is_owner_ = true;
249 : : }
250 : :
251 : 7 : return true;
252 : : }
253 : :
254 : 4 : bool CameraFrame::move_copy(CameraFrame& target) noexcept {
255 [ + + ]: 4 : if VUNLIKELY (!shallow_copy(target)) {
256 : 1 : return false;
257 : : }
258 : :
259 : 3 : is_owner_ = target.is_owner_;
260 : :
261 : 3 : target.channel_ = 0;
262 : 3 : target.height_ = 0;
263 : 3 : target.width_ = 0;
264 : 3 : target.freq_ = 0;
265 : 3 : target.format_ = kFormatUnknown;
266 : 3 : target.stream_ = kStreamUnknown;
267 : 3 : target.reserved_buf_ = 0;
268 : 3 : target.is_owner_ = false;
269 : 3 : target.data_ = nullptr;
270 : 3 : target.size_ = 0;
271 : :
272 : : #if defined(__GNUC__) && !defined(__clang__)
273 : : #pragma GCC diagnostic push
274 : : #pragma GCC diagnostic ignored "-Wclass-memaccess"
275 : : #if __GNUC__ >= 11
276 : : #pragma GCC diagnostic ignored "-Wstringop-overread"
277 : : #endif
278 : : #endif
279 : :
280 : 3 : std::memset(&target.header, 0, sizeof(header));
281 : :
282 : : #if defined(__GNUC__) && !defined(__clang__)
283 : : #pragma GCC diagnostic pop
284 : : #endif
285 : :
286 : 3 : return true;
287 : : }
288 : :
289 : 38 : bool CameraFrame::create(size_t _size) noexcept {
290 [ + + ]: 38 : if VUNLIKELY (_size == 0) {
291 : 1 : return false;
292 : : }
293 : :
294 [ + + + - : 37 : if (is_owner_ && data_ && size_ != 0) {
+ - ]
295 : 2 : Bytes::bytes_free(data_, size_);
296 : : }
297 : :
298 : 37 : size_ = _size;
299 : :
300 : 37 : data_ = Bytes::bytes_malloc(size_);
301 : :
302 : 37 : is_owner_ = true;
303 : :
304 : 37 : return true;
305 : : }
306 : :
307 : 4 : void CameraFrame::clear() noexcept {
308 [ + + + - : 4 : if (is_owner_ && data_ && size_ != 0) {
+ - ]
309 : 3 : Bytes::bytes_free(data_, size_);
310 : : }
311 : :
312 : 4 : channel_ = 0;
313 : 4 : height_ = 0;
314 : 4 : width_ = 0;
315 : 4 : freq_ = 0;
316 : 4 : format_ = kFormatUnknown;
317 : 4 : stream_ = kStreamUnknown;
318 : 4 : is_owner_ = false;
319 : 4 : data_ = nullptr;
320 : 4 : size_ = 0;
321 : :
322 : : #if defined(__GNUC__) && !defined(__clang__)
323 : : #pragma GCC diagnostic push
324 : : #pragma GCC diagnostic ignored "-Wclass-memaccess"
325 : : #if __GNUC__ >= 11
326 : : #pragma GCC diagnostic ignored "-Wstringop-overread"
327 : : #endif
328 : : #endif
329 : :
330 : 4 : std::memset(&header, 0, sizeof(header));
331 : :
332 : : #if defined(__GNUC__) && !defined(__clang__)
333 : : #pragma GCC diagnostic pop
334 : : #endif
335 : 4 : }
336 : :
337 : 5 : bool CameraFrame::shallow_copy(uint8_t* data, size_t size) noexcept {
338 [ + + + + : 5 : if VUNLIKELY (!data || size == 0) {
+ + ]
339 : 2 : return false;
340 : : }
341 : :
342 [ + + ]: 3 : if VUNLIKELY (data_ == data) {
343 : 1 : return false;
344 : : }
345 : :
346 [ - + - - : 2 : if (is_owner_ && data_ && size_ != 0) {
- - ]
347 : 0 : Bytes::bytes_free(data_, size_);
348 : : }
349 : :
350 : 2 : is_owner_ = false;
351 : :
352 : 2 : data_ = data;
353 : 2 : size_ = size;
354 : :
355 : 2 : return true;
356 : : }
357 : :
358 : 6 : bool CameraFrame::deep_copy(uint8_t* data, size_t size) noexcept {
359 [ + + + + : 6 : if VUNLIKELY (!data || size == 0) {
+ + ]
360 : 2 : return false;
361 : : }
362 : :
363 [ + + ]: 4 : if (is_owner_) {
364 [ - + ]: 2 : if VUNLIKELY (!data_) {
365 : : return false; // LCOV_EXCL_LINE GCOVR_EXCL_LINE
366 : : }
367 : :
368 [ + + ]: 2 : if VUNLIKELY (data_ == data) {
369 : 1 : return false;
370 : : }
371 : :
372 [ + - ]: 1 : if VUNLIKELY (size_ != size) {
373 : 1 : create(size);
374 : : }
375 : : } else {
376 : 2 : create(size);
377 : : }
378 : :
379 : 3 : std::memcpy(data_, data, size);
380 : :
381 : 3 : return true;
382 : : }
383 : :
384 : 1 : bool CameraFrame::fill_data(uint8_t* data, size_t size) noexcept { return deep_copy(data, size); }
385 : :
386 : 5 : uint32_t CameraFrame::channel() const noexcept { return channel_; }
387 : :
388 : 14 : uint32_t CameraFrame::width() const noexcept { return width_; }
389 : :
390 : 12 : uint32_t CameraFrame::height() const noexcept { return height_; }
391 : :
392 : 4 : uint32_t CameraFrame::freq() const noexcept { return freq_; }
393 : :
394 : 24 : CameraFrame::Format CameraFrame::format() const noexcept { return format_; }
395 : :
396 : 8 : CameraFrame::Stream CameraFrame::stream() const noexcept { return stream_; }
397 : :
398 : 35 : const uint8_t* CameraFrame::data() const noexcept { return data_; }
399 : :
400 : 29 : size_t CameraFrame::size() const noexcept { return size_; }
401 : :
402 : 22 : bool CameraFrame::is_owner() const noexcept { return is_owner_; }
403 : :
404 : 5 : void CameraFrame::set_channel(uint32_t channel) noexcept { channel_ = channel; }
405 : :
406 : 13 : void CameraFrame::set_width(uint32_t width) noexcept { width_ = width; }
407 : :
408 : 12 : void CameraFrame::set_height(uint32_t height) noexcept { height_ = height; }
409 : :
410 : 3 : void CameraFrame::set_freq(uint32_t freq) noexcept { freq_ = freq; }
411 : :
412 : 27 : void CameraFrame::set_format(Format format) noexcept { format_ = format; }
413 : :
414 : 8 : void CameraFrame::set_stream(Stream stream) noexcept { stream_ = stream; }
415 : :
416 : : } // namespace zerocopy
417 : :
418 : : } // namespace vlink
|