@@ -124,6 +124,18 @@
};
/**
* @brief Pipewire image assembled for encoding.
*/
struct img_descriptor_t: public egl::img_descriptor_t {
~img_descriptor_t() override {
if (data) {
delete[] data;
data = nullptr;
}
}
};
/**
* @brief PipeWire core, context, and stream setup used for screencast capture.
*/
class pipewire_t {
@@ -136,34 +148,44 @@
~pipewire_t() {
BOOST_LOG(debug) << "[pipewire] Destroying pipewire_t"sv;
pw_thread_loop_lock(loop);
try {
// Lock the frame mutex to stop fill_img
BOOST_LOG(debug) << "[pipewire] Stop fill_img"sv;
{
std::scoped_lock lock(stream_data.frame_mutex);
stream_data.frame_ready = false;
stream_data.current_buffer = nullptr;
cleanup_stream();
} catch (const std::exception &e) {
BOOST_LOG(error) << "[pipewire] Standard exception caught in ~pipewire_t cleanup_stream: "sv << e.what();
} catch (...) {
BOOST_LOG(error) << "[pipewire] Unknown exception caught in ~pipewire_t cleanup_stream"sv;
}
pw_thread_loop_lock(loop);
// Release pipewire stream
if (stream_data.stream) {
BOOST_LOG(debug) << "[pipewire] Disconnect stream"sv;
pw_stream_disconnect(stream_data.stream);
BOOST_LOG(debug) << "[pipewire] Destroy stream"sv;
pw_stream_destroy(stream_data.stream);
stream_data.stream = nullptr;
}
// Release pipewire core
if (core) {
BOOST_LOG(debug) << "[pipewire] Disconnect PW core"sv;
pw_core_disconnect(core);
core = nullptr;
}
// Release pipewire context
if (context) {
BOOST_LOG(debug) << "[pipewire] Destroy PW context"sv;
pw_context_destroy(context);
context = nullptr;
}
// Release pipewire file descriptor
pw_thread_loop_unlock(loop);
if (fd >= 0) {
BOOST_LOG(debug) << "[pipewire] Close pipewire_fd"sv;
close(fd);
}
// Release pipewire thread loop
BOOST_LOG(debug) << "[pipewire] Stop PW thread loop"sv;
pw_thread_loop_unlock(loop);
pw_thread_loop_stop(loop);
BOOST_LOG(debug) << "[pipewire] Destroy PW thread loop"sv;
pw_thread_loop_destroy(loop);
@@ -246,34 +268,6 @@
}
/**
* @brief Release the active PipeWire stream and listener.
*/
void cleanup_stream() {
BOOST_LOG(debug) << "[pipewire] Cleaning up stream"sv;
if (loop && stream_data.stream) {
pw_thread_loop_lock(loop);
// 1. Lock the frame mutex to stop fill_img
BOOST_LOG(debug) << "[pipewire] Stop fill_img"sv;
{
std::scoped_lock lock(stream_data.frame_mutex);
stream_data.frame_ready = false;
stream_data.current_buffer = nullptr;
}
if (stream_data.stream) {
BOOST_LOG(debug) << "[pipewire] Disconnect stream"sv;
pw_stream_disconnect(stream_data.stream);
BOOST_LOG(debug) << "[pipewire] Destroy stream"sv;
pw_stream_destroy(stream_data.stream);
stream_data.stream = nullptr;
}
pw_thread_loop_unlock(loop);
}
}
/**
* @brief Create the PipeWire stream if it is not already active.
*
* @param mem_type Mem type.
@@ -934,7 +928,7 @@
*/
std::shared_ptr<platf::img_t> alloc_img() override {
// Note: this img_t type is also used for memory buffers
auto img = std::make_shared<img_descriptor_t>();
auto img = std::make_shared<egl::img_descriptor_t>();
img->width = width;
img->height = height;
@@ -1067,11 +1061,6 @@
* @return Capture status reported to the streaming pipeline.
*/
int dummy_img(platf::img_t *img) override {
if (!img) {
return -1;
}
img->data = new std::uint8_t[img->height * img->row_pitch];
std::fill_n(img->data, img->height * img->row_pitch, 0);
// Empty images are recognized as dummies by the zero sequence number
return 0;
}