| 247 | } |
| 248 | |
| 249 | void video_encoder::encode(wivrn_session & cnx, |
| 250 | const to_headset::video_stream_data_shard::view_info_t & view_info, |
| 251 | uint64_t frame_index) |
| 252 | { |
| 253 | encode_slot = (encode_slot + 1) % num_slots; |
| 254 | |
| 255 | struct idle_setter |
| 256 | { |
| 257 | std::atomic_unsigned_lock_free & state; |
| 258 | ~idle_setter() |
| 259 | { |
| 260 | state = idle; |
| 261 | state.notify_all(); |
| 262 | } |
| 263 | }; |
| 264 | idle_setter i{state[encode_slot]}; |
| 265 | |
| 266 | if (state[encode_slot] == skip) |
| 267 | return; |
| 268 | |
| 269 | if (shared_sender) |
| 270 | shared_sender->wait_idle(this); |
| 271 | this->cnx = &cnx; |
| 272 | clock = cnx.get_offset(); |
| 273 | |
| 274 | auto encode_begin = os_monotonic_get_ns(); |
| 275 | timing_info = { |
| 276 | .encode_begin = clock.to_headset(encode_begin), |
| 277 | }; |
| 278 | |
| 279 | // Prepare the video shard template |
| 280 | shard.stream_item_idx = stream_idx; |
| 281 | shard.frame_idx = frame_index; |
| 282 | shard.shard_idx = 0; |
| 283 | shard.view_info = view_info; |
| 284 | shard.timing_info.reset(); |
| 285 | |
| 286 | auto data = encode(encode_slot, frame_index); |
| 287 | cnx.dump_time("encode_begin", frame_index, encode_begin, stream_idx); |
| 288 | cnx.dump_time("encode_end", frame_index, os_monotonic_get_ns(), stream_idx); |
| 289 | if (data) |
| 290 | { |
| 291 | timing_info.encode_end = clock.to_headset(os_monotonic_get_ns()); |
| 292 | assert(shared_sender); |
| 293 | shared_sender->push(std::move(*data)); |
| 294 | } |
| 295 | } |
| 296 | |
| 297 | void video_encoder::SendData(std::span<uint8_t> data, bool end_of_frame, bool control) |
| 298 | { |
no test coverage detected