| 295 | } |
| 296 | |
| 297 | void video_encoder::SendData(std::span<uint8_t> data, bool end_of_frame, bool control) |
| 298 | { |
| 299 | std::lock_guard lock(mutex); |
| 300 | if (end_of_frame) |
| 301 | { |
| 302 | timing_info.send_end = clock.to_headset(os_monotonic_get_ns()); |
| 303 | if (not timing_info.encode_end) |
| 304 | timing_info.encode_end = timing_info.send_end; |
| 305 | } |
| 306 | if (video_dump) |
| 307 | video_dump.write((char *)data.data(), data.size()); |
| 308 | if (shard.shard_idx == 0) |
| 309 | { |
| 310 | cnx->dump_time("send_begin", shard.frame_idx, os_monotonic_get_ns(), stream_idx); |
| 311 | timing_info.send_begin = clock.to_headset(os_monotonic_get_ns()); |
| 312 | } |
| 313 | |
| 314 | ssize_t max_payload_size = (cnx->has_stream() and not control) ? to_headset::video_stream_data_shard::max_payload_size : std::numeric_limits<uint32_t>::max(); |
| 315 | |
| 316 | auto begin = data.begin(); |
| 317 | auto end = data.end(); |
| 318 | while (begin != end) |
| 319 | { |
| 320 | const size_t payload_size = std::max(0z, max_payload_size - ssize_t(serialized_size(shard.view_info))); |
| 321 | auto next = std::min(end, begin + payload_size); |
| 322 | if (next == end) |
| 323 | { |
| 324 | if (end_of_frame) |
| 325 | shard.timing_info = timing_info; |
| 326 | } |
| 327 | shard.payload = {begin, next}; |
| 328 | try |
| 329 | { |
| 330 | if (control) |
| 331 | cnx->send_control(to_headset::video_stream_data_shard{shard}); |
| 332 | else |
| 333 | cnx->send_stream(to_headset::video_stream_data_shard{shard}); |
| 334 | } |
| 335 | catch (...) |
| 336 | { |
| 337 | // Ignore network errors |
| 338 | } |
| 339 | ++shard.shard_idx; |
| 340 | shard.view_info.reset(); |
| 341 | begin = next; |
| 342 | } |
| 343 | if (end_of_frame) |
| 344 | cnx->dump_time("send_end", shard.frame_idx, os_monotonic_get_ns(), stream_idx); |
| 345 | } |
| 346 | |
| 347 | } // namespace wivrn |
no test coverage detected