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 <cctype>
27 : : #include <cstdint>
28 : : #include <cstring>
29 : : #include <string_view>
30 : :
31 : : namespace vlink {
32 : :
33 : : namespace zerocopy {
34 : :
35 : : struct CameraFrameFormatEncoding final {
36 : : std::string_view name;
37 : : CameraFrame::Format format;
38 : : };
39 : :
40 : 8 : static std::string_view normalize_camera_encoding(std::string_view encoding, char (&BufferT)[64]) noexcept {
41 : 8 : size_t n = 0;
42 : :
43 [ + + ]: 49 : for (char c : encoding) {
44 [ - + ]: 41 : if (std::isspace(static_cast<unsigned char>(c)) != 0) {
45 : 0 : continue;
46 : : }
47 : :
48 [ - + ]: 41 : if VUNLIKELY (n + 1 >= sizeof(BufferT)) {
49 : 0 : return {};
50 : : }
51 : :
52 [ + + ]: 41 : BufferT[n++] = static_cast<char>(std::tolower(static_cast<unsigned char>(c == '-' ? '_' : c)));
53 : : }
54 : :
55 : 8 : BufferT[n] = '\0';
56 : :
57 : 8 : return std::string_view(BufferT, n);
58 : : }
59 : :
60 : : static constexpr CameraFrameFormatEncoding kCameraFrameEncodingAliases[] = {
61 : : {"yuv420", CameraFrame::kFormatYuv420},
62 : : {"i420", CameraFrame::kFormatYuv420},
63 : : {"yuv422", CameraFrame::kFormatYuv422},
64 : : {"yuv444", CameraFrame::kFormatYuv444},
65 : : {"nv12", CameraFrame::kFormatNv12},
66 : : {"nv21", CameraFrame::kFormatNv21},
67 : : {"yuyv", CameraFrame::kFormatYuyv},
68 : : {"yuyv422", CameraFrame::kFormatYuyv},
69 : : {"yuy2", CameraFrame::kFormatYuyv},
70 : : {"yvyu", CameraFrame::kFormatYvyu},
71 : : {"uyvy", CameraFrame::kFormatUyvy},
72 : : {"vyuy", CameraFrame::kFormatVyuy},
73 : : {"bgr8", CameraFrame::kFormatBgr888Packed},
74 : : {"rgb8", CameraFrame::kFormatRgb888Packed},
75 : : {"rgb8_planar", CameraFrame::kFormatRgb888Planar},
76 : : {"mono8", CameraFrame::kFormatMono8},
77 : : {"mono16", CameraFrame::kFormatMono16},
78 : : {"rgba8", CameraFrame::kFormatRgba8888Packed},
79 : : {"bgra8", CameraFrame::kFormatBgra8888Packed},
80 : : {"rgba8888", CameraFrame::kFormatRgba8888Packed},
81 : : {"bgra8888", CameraFrame::kFormatBgra8888Packed},
82 : : {"8uc1", CameraFrame::kFormatUint8C1},
83 : : {"8uc2", CameraFrame::kFormatUint8C2},
84 : : {"8uc3", CameraFrame::kFormatUint8C3},
85 : : {"8uc4", CameraFrame::kFormatUint8C4},
86 : : {"8sc1", CameraFrame::kFormatInt8C1},
87 : : {"8sc2", CameraFrame::kFormatInt8C2},
88 : : {"8sc3", CameraFrame::kFormatInt8C3},
89 : : {"8sc4", CameraFrame::kFormatInt8C4},
90 : : {"16uc1", CameraFrame::kFormatUint16C1},
91 : : {"16uc2", CameraFrame::kFormatUint16C2},
92 : : {"16uc3", CameraFrame::kFormatUint16C3},
93 : : {"16uc4", CameraFrame::kFormatUint16C4},
94 : : {"16sc1", CameraFrame::kFormatInt16C1},
95 : : {"16sc2", CameraFrame::kFormatInt16C2},
96 : : {"16sc3", CameraFrame::kFormatInt16C3},
97 : : {"16sc4", CameraFrame::kFormatInt16C4},
98 : : {"32sc1", CameraFrame::kFormatInt32C1},
99 : : {"32sc2", CameraFrame::kFormatInt32C2},
100 : : {"32sc3", CameraFrame::kFormatInt32C3},
101 : : {"32sc4", CameraFrame::kFormatInt32C4},
102 : : {"32fc1", CameraFrame::kFormatFloat32C1},
103 : : {"32fc2", CameraFrame::kFormatFloat32C2},
104 : : {"32fc3", CameraFrame::kFormatFloat32C3},
105 : : {"32fc4", CameraFrame::kFormatFloat32C4},
106 : : {"64fc1", CameraFrame::kFormatFloat64C1},
107 : : {"64fc2", CameraFrame::kFormatFloat64C2},
108 : : {"64fc3", CameraFrame::kFormatFloat64C3},
109 : : {"64fc4", CameraFrame::kFormatFloat64C4},
110 : : {"bayer_rggb8", CameraFrame::kFormatBayerRggb8},
111 : : {"bayer_bggr8", CameraFrame::kFormatBayerBggr8},
112 : : {"bayer_gbrg8", CameraFrame::kFormatBayerGbrg8},
113 : : {"bayer_grbg8", CameraFrame::kFormatBayerGrbg8},
114 : : {"bayer_rggb16", CameraFrame::kFormatBayerRggb16},
115 : : {"bayer_bggr16", CameraFrame::kFormatBayerBggr16},
116 : : {"bayer_gbrg16", CameraFrame::kFormatBayerGbrg16},
117 : : {"bayer_grbg16", CameraFrame::kFormatBayerGrbg16},
118 : : {"jpeg", CameraFrame::kFormatJpeg},
119 : : {"jpg", CameraFrame::kFormatJpeg},
120 : : {"png", CameraFrame::kFormatPng},
121 : : {"mjpeg", CameraFrame::kFormatMjpeg},
122 : : {"motion_jpeg", CameraFrame::kFormatMjpeg},
123 : : {"h264", CameraFrame::kFormatH264},
124 : : {"avc", CameraFrame::kFormatH264},
125 : : {"h265", CameraFrame::kFormatH265},
126 : : {"hevc", CameraFrame::kFormatH265},
127 : : {"h266", CameraFrame::kFormatH266},
128 : : {"vvc", CameraFrame::kFormatH266},
129 : : {"av1", CameraFrame::kFormatAv1},
130 : : {"webp", CameraFrame::kFormatWebp},
131 : : };
132 : :
133 : : static constexpr CameraFrameFormatEncoding kCameraFrameCanonicalEncodings[] = {
134 : : {"unknown", CameraFrame::kFormatUnknown},
135 : : {"yuv420", CameraFrame::kFormatYuv420},
136 : : {"yuv422", CameraFrame::kFormatYuv422},
137 : : {"yuv444", CameraFrame::kFormatYuv444},
138 : : {"nv12", CameraFrame::kFormatNv12},
139 : : {"nv21", CameraFrame::kFormatNv21},
140 : : {"yuyv", CameraFrame::kFormatYuyv},
141 : : {"yvyu", CameraFrame::kFormatYvyu},
142 : : {"uyvy", CameraFrame::kFormatUyvy},
143 : : {"vyuy", CameraFrame::kFormatVyuy},
144 : : {"bgr8", CameraFrame::kFormatBgr888Packed},
145 : : {"rgb8", CameraFrame::kFormatRgb888Packed},
146 : : {"rgb8_planar", CameraFrame::kFormatRgb888Planar},
147 : : {"mono8", CameraFrame::kFormatMono8},
148 : : {"mono16", CameraFrame::kFormatMono16},
149 : : {"rgba8", CameraFrame::kFormatRgba8888Packed},
150 : : {"bgra8", CameraFrame::kFormatBgra8888Packed},
151 : : {"8UC1", CameraFrame::kFormatUint8C1},
152 : : {"8UC2", CameraFrame::kFormatUint8C2},
153 : : {"8UC3", CameraFrame::kFormatUint8C3},
154 : : {"8UC4", CameraFrame::kFormatUint8C4},
155 : : {"8SC1", CameraFrame::kFormatInt8C1},
156 : : {"8SC2", CameraFrame::kFormatInt8C2},
157 : : {"8SC3", CameraFrame::kFormatInt8C3},
158 : : {"8SC4", CameraFrame::kFormatInt8C4},
159 : : {"16UC1", CameraFrame::kFormatUint16C1},
160 : : {"16UC2", CameraFrame::kFormatUint16C2},
161 : : {"16UC3", CameraFrame::kFormatUint16C3},
162 : : {"16UC4", CameraFrame::kFormatUint16C4},
163 : : {"16SC1", CameraFrame::kFormatInt16C1},
164 : : {"16SC2", CameraFrame::kFormatInt16C2},
165 : : {"16SC3", CameraFrame::kFormatInt16C3},
166 : : {"16SC4", CameraFrame::kFormatInt16C4},
167 : : {"32SC1", CameraFrame::kFormatInt32C1},
168 : : {"32SC2", CameraFrame::kFormatInt32C2},
169 : : {"32SC3", CameraFrame::kFormatInt32C3},
170 : : {"32SC4", CameraFrame::kFormatInt32C4},
171 : : {"32FC1", CameraFrame::kFormatFloat32C1},
172 : : {"32FC2", CameraFrame::kFormatFloat32C2},
173 : : {"32FC3", CameraFrame::kFormatFloat32C3},
174 : : {"32FC4", CameraFrame::kFormatFloat32C4},
175 : : {"64FC1", CameraFrame::kFormatFloat64C1},
176 : : {"64FC2", CameraFrame::kFormatFloat64C2},
177 : : {"64FC3", CameraFrame::kFormatFloat64C3},
178 : : {"64FC4", CameraFrame::kFormatFloat64C4},
179 : : {"bayer_rggb8", CameraFrame::kFormatBayerRggb8},
180 : : {"bayer_bggr8", CameraFrame::kFormatBayerBggr8},
181 : : {"bayer_gbrg8", CameraFrame::kFormatBayerGbrg8},
182 : : {"bayer_grbg8", CameraFrame::kFormatBayerGrbg8},
183 : : {"bayer_rggb16", CameraFrame::kFormatBayerRggb16},
184 : : {"bayer_bggr16", CameraFrame::kFormatBayerBggr16},
185 : : {"bayer_gbrg16", CameraFrame::kFormatBayerGbrg16},
186 : : {"bayer_grbg16", CameraFrame::kFormatBayerGrbg16},
187 : : {"jpeg", CameraFrame::kFormatJpeg},
188 : : {"h264", CameraFrame::kFormatH264},
189 : : {"h265", CameraFrame::kFormatH265},
190 : : {"mjpeg", CameraFrame::kFormatMjpeg},
191 : : {"png", CameraFrame::kFormatPng},
192 : : {"webp", CameraFrame::kFormatWebp},
193 : : {"h266", CameraFrame::kFormatH266},
194 : : {"av1", CameraFrame::kFormatAv1},
195 : : };
196 : :
197 : : // CameraFrame
198 : 127 : CameraFrame::CameraFrame() noexcept {
199 : : #if defined(__arm__) || defined(__x86__) || defined(__i386__)
200 : : #ifndef __ANDROID__
201 : : #warning "[CameraFrame] No support for 32-bit architecture."
202 : : #endif
203 : : #else
204 : : static_assert(sizeof(CameraFrame) == 80, "Sizeof must be 80 bytes.");
205 : : #endif
206 : 127 : }
207 : :
208 : 129 : CameraFrame::~CameraFrame() noexcept {
209 [ + + + - : 129 : if (is_owner_ && data_ && size_ != 0) {
+ - ]
210 : 40 : Bytes::bytes_free(data_, size_);
211 : : }
212 : 129 : }
213 : :
214 : 1 : CameraFrame::CameraFrame(const CameraFrame& target) noexcept { deep_copy(target); }
215 : :
216 : 1 : CameraFrame::CameraFrame(CameraFrame&& target) noexcept { move_copy(target); }
217 : :
218 : 1 : CameraFrame& CameraFrame::operator=(const CameraFrame& target) noexcept {
219 [ - + ]: 1 : if VUNLIKELY (this == &target) {
220 : 0 : return *this;
221 : : }
222 : :
223 : 1 : deep_copy(target);
224 : :
225 : 1 : return *this;
226 : : }
227 : :
228 : 1 : CameraFrame& CameraFrame::operator=(CameraFrame&& target) noexcept {
229 [ - + ]: 1 : if VUNLIKELY (this == &target) {
230 : 0 : return *this;
231 : : }
232 : :
233 : 1 : move_copy(target);
234 : :
235 : 1 : return *this;
236 : : }
237 : :
238 : 13 : bool CameraFrame::operator<<(const Bytes& bytes) noexcept {
239 : : static constexpr size_t kMagicNumberBeginSize = sizeof(kMagicNumberBegin);
240 : : static constexpr size_t kVersionSize = sizeof(kWireVersion);
241 : : // static constexpr size_t kMagicNumberEndSize = sizeof(kMagicNumberEnd);
242 : :
243 [ + + ]: 13 : if VUNLIKELY (bytes.empty()) {
244 : 1 : return false;
245 : : }
246 : :
247 [ + + ]: 12 : if VUNLIKELY (!check_valid(bytes)) {
248 : 2 : return false;
249 : : }
250 : :
251 : 10 : uint32_t wire_version = 0;
252 : 10 : std::memcpy(&wire_version, bytes.data() + kMagicNumberBeginSize, kVersionSize);
253 : :
254 [ - + ]: 10 : if VUNLIKELY (version_major(wire_version) != version_major(kWireVersion)) {
255 : 0 : return false;
256 : : }
257 : :
258 [ + + + - : 10 : if (is_owner_ && data_ && size_ != 0) {
+ - ]
259 : 1 : Bytes::bytes_free(data_, size_);
260 : : }
261 : :
262 : : #if defined(__GNUC__) && !defined(__clang__)
263 : : #pragma GCC diagnostic push
264 : : #pragma GCC diagnostic ignored "-Wclass-memaccess"
265 : : #if __GNUC__ >= 11
266 : : #pragma GCC diagnostic ignored "-Wstringop-overread"
267 : : #endif
268 : : #endif
269 : :
270 : 10 : auto* target_ptr = reinterpret_cast<uint8_t*>(this);
271 : :
272 : 10 : std::memcpy(target_ptr, bytes.data() + kMagicNumberBeginSize + kVersionSize, sizeof(CameraFrame));
273 : :
274 : : #if defined(__GNUC__) && !defined(__clang__)
275 : : #pragma GCC diagnostic pop
276 : : #endif
277 : :
278 : 10 : data_ = const_cast<uint8_t*>(bytes.data() + kMagicNumberBeginSize + kVersionSize + sizeof(CameraFrame));
279 : 10 : is_owner_ = false;
280 : :
281 [ + + ]: 10 : if VUNLIKELY (bytes.size() != get_serialized_size()) {
282 : 1 : clear();
283 : 1 : return false;
284 : : }
285 : :
286 : 9 : return true;
287 : : }
288 : :
289 : 13 : bool CameraFrame::operator>>(Bytes& bytes) const noexcept {
290 : : static constexpr size_t kMagicNumberBeginSize = sizeof(kMagicNumberBegin);
291 : : static constexpr size_t kVersionSize = sizeof(kWireVersion);
292 : : static constexpr size_t kMagicNumberEndSize = sizeof(kMagicNumberEnd);
293 : :
294 [ + + + + : 13 : if (bytes.empty() || bytes.size() != get_serialized_size()) {
+ + ]
295 : 11 : bytes = Bytes::create(get_serialized_size());
296 : :
297 [ - + ]: 11 : if VUNLIKELY (bytes.empty()) {
298 : 0 : return false;
299 : : }
300 : : }
301 : :
302 : 13 : std::memcpy(bytes.data(), &kMagicNumberBegin, kMagicNumberBeginSize);
303 : :
304 : 13 : std::memcpy(bytes.data() + kMagicNumberBeginSize, &kWireVersion, kVersionSize);
305 : :
306 : : // NOLINTNEXTLINE(bugprone-undefined-memory-manipulation)
307 : 13 : std::memcpy(bytes.data() + kMagicNumberBeginSize + kVersionSize, this, sizeof(CameraFrame));
308 : :
309 : 13 : const auto data_offset = reinterpret_cast<const uint8_t*>(&data_) - reinterpret_cast<const uint8_t*>(this);
310 : 13 : const size_t data_pointer_size = sizeof(data_);
311 : 13 : std::memset(bytes.data() + kMagicNumberBeginSize + kVersionSize + data_offset, 0, data_pointer_size);
312 : :
313 [ + + + - : 13 : if VLIKELY (data_ != nullptr && size_ != 0) {
+ + ]
314 : 12 : std::memcpy(bytes.data() + kMagicNumberBeginSize + kVersionSize + sizeof(CameraFrame), data_, size_);
315 : : }
316 : :
317 : 13 : std::memcpy(bytes.data() + kMagicNumberBeginSize + kVersionSize + sizeof(CameraFrame) + size_, &kMagicNumberEnd,
318 : : kMagicNumberEndSize);
319 : :
320 : 13 : return true;
321 : : }
322 : :
323 : 19 : bool CameraFrame::check_valid(const Bytes& bytes) noexcept {
324 : : static constexpr size_t kMagicNumberBeginSize = sizeof(kMagicNumberBegin);
325 : : static constexpr size_t kVersionSize = sizeof(kWireVersion);
326 : : static constexpr size_t kMagicNumberEndSize = sizeof(kMagicNumberEnd);
327 : :
328 [ + + ]: 19 : if VUNLIKELY (bytes.size() < kMagicNumberBeginSize + kVersionSize + sizeof(CameraFrame) + kMagicNumberEndSize) {
329 : 2 : return false;
330 : : }
331 : :
332 : 17 : uint32_t check_magic = 0;
333 : :
334 : 17 : std::memcpy(&check_magic, bytes.begin(), kMagicNumberBeginSize);
335 : :
336 [ + + ]: 17 : if VUNLIKELY (check_magic != kMagicNumberBegin) {
337 : 1 : return false;
338 : : }
339 : :
340 : 16 : uint32_t wire_version = 0;
341 : 16 : std::memcpy(&wire_version, bytes.data() + kMagicNumberBeginSize, kVersionSize);
342 : :
343 [ + + ]: 16 : if VUNLIKELY (version_major(wire_version) != version_major(kWireVersion)) {
344 : 2 : return false;
345 : : }
346 : :
347 : 14 : std::memcpy(&check_magic, bytes.end() - kMagicNumberEndSize, kMagicNumberEndSize);
348 : :
349 [ + + ]: 14 : if VUNLIKELY (check_magic != kMagicNumberEnd) {
350 : 1 : return false;
351 : : }
352 : :
353 : 13 : return true;
354 : : }
355 : :
356 : 8 : CameraFrame::Format CameraFrame::format_from_encoding(std::string_view encoding) noexcept {
357 : : char normalized[64];
358 : 8 : const auto key = normalize_camera_encoding(encoding, normalized);
359 [ - + ]: 8 : if (key.empty()) {
360 : 0 : return kFormatUnknown;
361 : : }
362 : :
363 [ + - ]: 331 : for (const auto& item : kCameraFrameEncodingAliases) {
364 [ + + ]: 331 : if (key == item.name) {
365 : 8 : return item.format;
366 : : }
367 : : }
368 : :
369 : 0 : return kFormatUnknown;
370 : : }
371 : :
372 : 2 : std::string_view CameraFrame::encoding_from_format(Format format) noexcept {
373 [ + - ]: 39 : for (const auto& item : kCameraFrameCanonicalEncodings) {
374 [ + + ]: 39 : if (format == item.format) {
375 : 2 : return item.name;
376 : : }
377 : : }
378 : :
379 : 0 : return "unknown";
380 : : }
381 : :
382 : 29 : size_t CameraFrame::get_serialized_size() const noexcept {
383 : : static constexpr size_t kMagicNumberBeginSize = sizeof(kMagicNumberBegin);
384 : : static constexpr size_t kVersionSize = sizeof(kWireVersion);
385 : : static constexpr size_t kMagicNumberEndSize = sizeof(kMagicNumberEnd);
386 : :
387 : 29 : return kMagicNumberBeginSize + kVersionSize + sizeof(CameraFrame) + size_ + kMagicNumberEndSize;
388 : : }
389 : :
390 [ + + + - ]: 13 : bool CameraFrame::is_valid() const noexcept { return data_ != nullptr && size_ != 0; }
391 : :
392 : 14 : bool CameraFrame::shallow_copy(const CameraFrame& target) noexcept {
393 [ + + ]: 14 : if VUNLIKELY (this == &target) {
394 : 2 : return false;
395 : : }
396 : :
397 [ + + + - : 12 : if (is_owner_ && data_ && size_ != 0) {
+ - ]
398 : 1 : const auto current = reinterpret_cast<uintptr_t>(data_);
399 : 1 : const auto source = reinterpret_cast<uintptr_t>(target.data_);
400 : :
401 [ + - + - : 1 : if VUNLIKELY (source >= current && source - current < size_) {
+ - ]
402 : 1 : return false;
403 : : }
404 : :
405 : 0 : Bytes::bytes_free(data_, size_);
406 : : }
407 : :
408 : 11 : header = target.header;
409 : :
410 : 11 : channel_ = target.channel_;
411 : 11 : height_ = target.height_;
412 : 11 : width_ = target.width_;
413 : 11 : freq_ = target.freq_;
414 : 11 : format_ = target.format_;
415 : 11 : stream_ = target.stream_;
416 : 11 : reserved_buf_ = target.reserved_buf_;
417 : 11 : is_owner_ = false;
418 : 11 : data_ = target.data_;
419 : 11 : size_ = target.size_;
420 : :
421 : 11 : return true;
422 : : }
423 : :
424 : 10 : bool CameraFrame::deep_copy(const CameraFrame& target) noexcept {
425 [ + + + - : 10 : if VLIKELY (data_ && is_owner_ && target.data_ && size_ != 0 && size_ == target.size_) {
+ + + - +
+ + - + +
+ - + + ]
426 : 3 : const auto current = reinterpret_cast<uintptr_t>(data_);
427 : 3 : const auto source = reinterpret_cast<uintptr_t>(target.data_);
428 : :
429 [ + + + - : 3 : if VUNLIKELY (source >= current && source - current < size_) {
+ + ]
430 : 2 : return false;
431 : : }
432 : :
433 : 1 : header = target.header;
434 : :
435 : 1 : channel_ = target.channel_;
436 : 1 : height_ = target.height_;
437 : 1 : width_ = target.width_;
438 : 1 : freq_ = target.freq_;
439 : 1 : format_ = target.format_;
440 : 1 : stream_ = target.stream_;
441 : 1 : reserved_buf_ = target.reserved_buf_;
442 : :
443 : 1 : std::memcpy(data_, target.data_, size_);
444 : :
445 : 1 : return true;
446 : : }
447 : :
448 [ - + ]: 7 : if VUNLIKELY (!shallow_copy(target)) {
449 : 0 : return false;
450 : : }
451 : :
452 [ + - + - ]: 7 : if (data_ && size_ != 0) {
453 : 7 : auto* target_data = data_;
454 : 7 : data_ = Bytes::bytes_malloc(size_);
455 : :
456 [ - + ]: 7 : if VUNLIKELY (!data_) {
457 : 0 : size_ = 0;
458 : 0 : return false;
459 : : }
460 : :
461 : 7 : std::memcpy(data_, target_data, size_);
462 : 7 : is_owner_ = true;
463 : : }
464 : :
465 : 7 : return true;
466 : : }
467 : :
468 : 4 : bool CameraFrame::move_copy(CameraFrame& target) noexcept {
469 [ + + ]: 4 : if VUNLIKELY (!shallow_copy(target)) {
470 : 1 : return false;
471 : : }
472 : :
473 : 3 : is_owner_ = target.is_owner_;
474 : :
475 : 3 : target.channel_ = 0;
476 : 3 : target.height_ = 0;
477 : 3 : target.width_ = 0;
478 : 3 : target.freq_ = 0;
479 : 3 : target.format_ = kFormatUnknown;
480 : 3 : target.stream_ = kStreamUnknown;
481 : 3 : target.reserved_buf_ = 0;
482 : 3 : target.is_owner_ = false;
483 : 3 : target.data_ = nullptr;
484 : 3 : target.size_ = 0;
485 : :
486 : : #if defined(__GNUC__) && !defined(__clang__)
487 : : #pragma GCC diagnostic push
488 : : #pragma GCC diagnostic ignored "-Wclass-memaccess"
489 : : #if __GNUC__ >= 11
490 : : #pragma GCC diagnostic ignored "-Wstringop-overread"
491 : : #endif
492 : : #endif
493 : :
494 : 3 : std::memset(&target.header, 0, sizeof(header));
495 : :
496 : : #if defined(__GNUC__) && !defined(__clang__)
497 : : #pragma GCC diagnostic pop
498 : : #endif
499 : :
500 : 3 : return true;
501 : : }
502 : :
503 : 40 : bool CameraFrame::create(size_t _size) noexcept {
504 [ + + ]: 40 : if VUNLIKELY (_size == 0) {
505 : 1 : return false;
506 : : }
507 : :
508 [ + + + - : 39 : if (is_owner_ && data_ && size_ != 0) {
+ - ]
509 : 2 : Bytes::bytes_free(data_, size_);
510 : : }
511 : :
512 : 39 : data_ = Bytes::bytes_malloc(_size);
513 : :
514 [ - + ]: 39 : if VUNLIKELY (!data_) {
515 : 0 : size_ = 0;
516 : 0 : is_owner_ = false;
517 : 0 : return false;
518 : : }
519 : :
520 : 39 : size_ = _size;
521 : 39 : is_owner_ = true;
522 : :
523 : 39 : return true;
524 : : }
525 : :
526 : 4 : void CameraFrame::clear() noexcept {
527 [ + + + - : 4 : if (is_owner_ && data_ && size_ != 0) {
+ - ]
528 : 3 : Bytes::bytes_free(data_, size_);
529 : : }
530 : :
531 : 4 : channel_ = 0;
532 : 4 : height_ = 0;
533 : 4 : width_ = 0;
534 : 4 : freq_ = 0;
535 : 4 : format_ = kFormatUnknown;
536 : 4 : stream_ = kStreamUnknown;
537 : 4 : is_owner_ = false;
538 : 4 : data_ = nullptr;
539 : 4 : size_ = 0;
540 : :
541 : : #if defined(__GNUC__) && !defined(__clang__)
542 : : #pragma GCC diagnostic push
543 : : #pragma GCC diagnostic ignored "-Wclass-memaccess"
544 : : #if __GNUC__ >= 11
545 : : #pragma GCC diagnostic ignored "-Wstringop-overread"
546 : : #endif
547 : : #endif
548 : :
549 : 4 : std::memset(&header, 0, sizeof(header));
550 : :
551 : : #if defined(__GNUC__) && !defined(__clang__)
552 : : #pragma GCC diagnostic pop
553 : : #endif
554 : 4 : }
555 : :
556 : 7 : bool CameraFrame::shallow_copy(uint8_t* data, size_t size) noexcept {
557 [ + + + + : 7 : if VUNLIKELY (!data || size == 0) {
+ + ]
558 : 2 : return false;
559 : : }
560 : :
561 [ + + ]: 5 : if VUNLIKELY (data_ == data) {
562 : 1 : return false;
563 : : }
564 : :
565 [ + + + - : 4 : if (is_owner_ && data_ && size_ != 0) {
+ - ]
566 : 1 : const auto current = reinterpret_cast<uintptr_t>(data_);
567 : 1 : const auto source = reinterpret_cast<uintptr_t>(data);
568 : :
569 [ + - + - : 1 : if VUNLIKELY (source >= current && source - current < size_) {
+ - ]
570 : 1 : return false;
571 : : }
572 : :
573 : 0 : Bytes::bytes_free(data_, size_);
574 : : }
575 : :
576 : 3 : is_owner_ = false;
577 : :
578 : 3 : data_ = data;
579 : 3 : size_ = size;
580 : :
581 : 3 : return true;
582 : : }
583 : :
584 : 7 : bool CameraFrame::deep_copy(uint8_t* data, size_t size) noexcept {
585 [ + + + + : 7 : if VUNLIKELY (!data || size == 0) {
+ + ]
586 : 2 : return false;
587 : : }
588 : :
589 [ + + ]: 5 : if (is_owner_) {
590 [ - + ]: 3 : if VUNLIKELY (!data_) {
591 : : return false; // LCOV_EXCL_LINE GCOVR_EXCL_LINE
592 : : }
593 : :
594 : 3 : const auto current = reinterpret_cast<uintptr_t>(data_);
595 : 3 : const auto source = reinterpret_cast<uintptr_t>(data);
596 : :
597 [ + + + - : 3 : if VUNLIKELY (source >= current && source - current < size_) {
+ + ]
598 : 2 : return false;
599 : : }
600 : :
601 [ + - - + : 1 : if VUNLIKELY (size_ != size && !create(size)) {
- + ]
602 : 0 : return false;
603 : : }
604 [ - + ]: 2 : } else if VUNLIKELY (!create(size)) {
605 : 0 : return false;
606 : : }
607 : :
608 : 3 : std::memcpy(data_, data, size);
609 : :
610 : 3 : return true;
611 : : }
612 : :
613 : 1 : bool CameraFrame::fill_data(uint8_t* data, size_t size) noexcept { return deep_copy(data, size); }
614 : :
615 : 13 : uint32_t CameraFrame::channel() const noexcept { return channel_; }
616 : :
617 : 21 : uint32_t CameraFrame::width() const noexcept { return width_; }
618 : :
619 : 17 : uint32_t CameraFrame::height() const noexcept { return height_; }
620 : :
621 : 8 : uint32_t CameraFrame::freq() const noexcept { return freq_; }
622 : :
623 : 73 : CameraFrame::Format CameraFrame::format() const noexcept { return format_; }
624 : :
625 : 10 : CameraFrame::Stream CameraFrame::stream() const noexcept { return stream_; }
626 : :
627 : 37 : const uint8_t* CameraFrame::data() const noexcept { return data_; }
628 : :
629 : 33 : size_t CameraFrame::size() const noexcept { return size_; }
630 : :
631 : 23 : bool CameraFrame::is_owner() const noexcept { return is_owner_; }
632 : :
633 : 5 : void CameraFrame::set_channel(uint32_t channel) noexcept { channel_ = channel; }
634 : :
635 : 14 : void CameraFrame::set_width(uint32_t width) noexcept { width_ = width; }
636 : :
637 : 13 : void CameraFrame::set_height(uint32_t height) noexcept { height_ = height; }
638 : :
639 : 3 : void CameraFrame::set_freq(uint32_t freq) noexcept { freq_ = freq; }
640 : :
641 : 73 : void CameraFrame::set_format(Format format) noexcept { format_ = format; }
642 : :
643 : 8 : void CameraFrame::set_stream(Stream stream) noexcept { stream_ = stream; }
644 : :
645 : : } // namespace zerocopy
646 : :
647 : : } // namespace vlink
|