| 361 | } |
| 362 | |
| 363 | bool PipeWireScreencap::screencap(cv::Mat& image) |
| 364 | { |
| 365 | // Lazy init: try once on first screencap() call |
| 366 | if (!connected_ && !open_attempted_) { |
| 367 | open_attempted_ = true; |
| 368 | if (!open()) { |
| 369 | return false; |
| 370 | } |
| 371 | } |
| 372 | |
| 373 | if (!connected_) { |
| 374 | return false; |
| 375 | } |
| 376 | |
| 377 | // Wait for the first frame with a timeout. |
| 378 | // Subsequent calls return the cached frame immediately without waiting. |
| 379 | std::unique_lock<std::mutex> lock(frame_mutex_); |
| 380 | if (latest_frame_.empty()) { |
| 381 | if (!frame_cv_.wait_for(lock, std::chrono::seconds(2), [this]() { return !latest_frame_.empty(); })) { |
| 382 | LogError << "Timeout waiting for first PipeWire frame"; |
| 383 | return false; |
| 384 | } |
| 385 | } |
| 386 | |
| 387 | latest_frame_.copyTo(image); |
| 388 | return true; |
| 389 | } |
| 390 | |
| 391 | // =========================================================================== |
| 392 | // D-Bus implementation |