OpenShot Library | libopenshot  1.0.0
WaylandBufferUtilities.h
Go to the documentation of this file.
1 
6 // Copyright (c) 2008-2026 OpenShot Studios, LLC
7 //
8 // SPDX-License-Identifier: LGPL-3.0-or-later
9 
10 #ifndef OPENSHOT_WAYLAND_BUFFER_UTILITIES_H
11 #define OPENSHOT_WAYLAND_BUFFER_UTILITIES_H
12 
13 #include <algorithm>
14 #include <cstddef>
15 #include <cstdint>
16 #include <cstring>
17 #include <limits>
18 
20 {
22  {
23  size_t offset = 0;
24  size_t valid_size = 0;
25  int stride = 0;
26  int crop_x = 0;
27  int crop_y = 0;
28  int width = 0;
29  int height = 0;
30  bool valid = false;
31  };
32 
34  size_t max_size,
35  size_t chunk_offset,
36  size_t chunk_size,
37  int chunk_stride,
38  int stream_width,
39  int stream_height,
40  int crop_x,
41  int crop_y,
42  int crop_width,
43  int crop_height)
44  {
45  PackedVideoLayout layout;
46  if (max_size == 0 || stream_width <= 0 || stream_height <= 0
47  || stream_width > std::numeric_limits<int>::max() / 4
48  || chunk_stride < 0) {
49  return layout;
50  }
51 
52  layout.offset = chunk_offset % max_size;
53  layout.valid_size = std::min(chunk_size, max_size);
54  layout.stride = chunk_stride > 0 ? chunk_stride : stream_width * 4;
55  if (layout.stride < 4 || layout.valid_size < static_cast<size_t>(layout.stride)) {
56  return layout;
57  }
58 
59  const int readable_width = std::min(
60  stream_width,
61  layout.stride / 4);
62  const int readable_height = std::min(
63  stream_height,
64  static_cast<int>(layout.valid_size / static_cast<size_t>(layout.stride)));
65 
66  layout.crop_x = std::max(0, crop_x);
67  layout.crop_y = std::max(0, crop_y);
68  if (layout.crop_x >= readable_width || layout.crop_y >= readable_height) {
69  return layout;
70  }
71 
72  const int requested_width = crop_width > 0
73  ? crop_width
74  : stream_width - layout.crop_x;
75  const int requested_height = crop_height > 0
76  ? crop_height
77  : stream_height - layout.crop_y;
78  layout.width = std::min(requested_width, readable_width - layout.crop_x);
79  layout.height = std::min(requested_height, readable_height - layout.crop_y);
80 
81  // H.264 requires even dimensions, and capture callers already expect them.
82  layout.width -= layout.width % 2;
83  layout.height -= layout.height % 2;
84  if (layout.width <= 0 || layout.height <= 0) {
85  return layout;
86  }
87 
88  const size_t final_row_end =
89  static_cast<size_t>(layout.crop_y + layout.height - 1) * layout.stride
90  + static_cast<size_t>(layout.crop_x + layout.width) * 4;
91  if (final_row_end > layout.valid_size) {
92  return layout;
93  }
94 
95  layout.valid = true;
96  return layout;
97  }
98 
99  inline int DamageFrameWaitMilliseconds(int fps_num, int fps_den, bool have_last_frame)
100  {
101  if (!have_last_frame) {
102  return 5000;
103  }
104  const double fps = fps_num > 0 && fps_den > 0
105  ? static_cast<double>(fps_num) / fps_den
106  : 30.0;
107  return std::max(1, static_cast<int>(1000.0 / std::max(1.0, fps)));
108  }
109 
110  inline bool CopyWrappedBytes(
111  const uint8_t* source,
112  size_t max_size,
113  size_t chunk_offset,
114  size_t logical_offset,
115  uint8_t* destination,
116  size_t byte_count)
117  {
118  if (!source || !destination || max_size == 0 || byte_count > max_size) {
119  return false;
120  }
121  const size_t physical_offset = (
122  (chunk_offset % max_size) + (logical_offset % max_size)
123  ) % max_size;
124  const size_t first_size = std::min(byte_count, max_size - physical_offset);
125  std::memcpy(destination, source + physical_offset, first_size);
126  if (first_size < byte_count) {
127  std::memcpy(destination + first_size, source, byte_count - first_size);
128  }
129  return true;
130  }
131 }
132 
133 #endif
bool CopyWrappedBytes(const uint8_t *source, size_t max_size, size_t chunk_offset, size_t logical_offset, uint8_t *destination, size_t byte_count)
PackedVideoLayout ResolvePackedVideoLayout(size_t max_size, size_t chunk_offset, size_t chunk_size, int chunk_stride, int stream_width, int stream_height, int crop_x, int crop_y, int crop_width, int crop_height)
int DamageFrameWaitMilliseconds(int fps_num, int fps_den, bool have_last_frame)