screencast: Convert event handlers into methods

ScreencastStream is a C++ class, but we're having C style event handling
as static functions within the class. Mixing two styles within a class
isn't very clear.

We can turn them into normal methods with some thin wrapper functions
round the event handling.
master
David Edmundson 1 year ago
parent 5ef0b775ef
commit b1e6deee3f

@ -71,35 +71,34 @@ static spa_video_format drmFourCCToSpaVideoFormat(quint32 format)
}
}
void ScreenCastStream::onStreamStateChanged(void *data, pw_stream_state old, pw_stream_state state, const char *error_message)
void ScreenCastStream::onStreamStateChanged(pw_stream_state old, pw_stream_state state, const char *error_message)
{
ScreenCastStream *pw = static_cast<ScreenCastStream *>(data);
qCDebug(KWIN_SCREENCAST) << "state changed" << pw_stream_state_as_string(old) << " -> " << pw_stream_state_as_string(state) << error_message;
pw->m_streaming = false;
pw->m_pendingBuffer = nullptr;
pw->m_pendingNotifier.reset();
pw->m_pendingFence.reset();
m_streaming = false;
m_pendingBuffer = nullptr;
m_pendingNotifier.reset();
m_pendingFence.reset();
switch (state) {
case PW_STREAM_STATE_ERROR:
qCWarning(KWIN_SCREENCAST) << "Stream error: " << error_message;
break;
case PW_STREAM_STATE_PAUSED:
if (pw->nodeId() == 0 && pw->m_pwStream) {
pw->m_pwNodeId = pw_stream_get_node_id(pw->m_pwStream);
Q_EMIT pw->streamReady(pw->nodeId());
if (nodeId() == 0 && m_pwStream) {
m_pwNodeId = pw_stream_get_node_id(m_pwStream);
Q_EMIT streamReady(nodeId());
}
break;
case PW_STREAM_STATE_STREAMING:
pw->m_streaming = true;
Q_EMIT pw->startStreaming();
m_streaming = true;
Q_EMIT startStreaming();
break;
case PW_STREAM_STATE_CONNECTING:
break;
case PW_STREAM_STATE_UNCONNECTED:
if (!pw->m_stopped) {
Q_EMIT pw->stopStreaming();
if (!m_stopped) {
Q_EMIT stopStreaming();
}
break;
}
@ -154,14 +153,13 @@ void ScreenCastStream::newStreamParams()
pw_stream_update_params(m_pwStream, params.data(), params.count());
}
void ScreenCastStream::onStreamParamChanged(void *data, uint32_t id, const struct spa_pod *format)
void ScreenCastStream::onStreamParamChanged(uint32_t id, const struct spa_pod *format)
{
if (!format || id != SPA_PARAM_Format) {
return;
}
ScreenCastStream *pw = static_cast<ScreenCastStream *>(data);
spa_format_video_raw_parse(format, &pw->m_videoFormat);
spa_format_video_raw_parse(format, &m_videoFormat);
auto modifierProperty = spa_pod_find_prop(format, nullptr, SPA_FORMAT_VIDEO_modifier);
QVector<uint64_t> receivedModifiers;
if (modifierProperty) {
@ -174,46 +172,45 @@ void ScreenCastStream::onStreamParamChanged(void *data, uint32_t id, const struc
std::sort(receivedModifiers.begin(), receivedModifiers.end());
receivedModifiers.erase(std::unique(receivedModifiers.begin(), receivedModifiers.end()), receivedModifiers.end());
}
if (modifierProperty && (!pw->m_dmabufParams || !receivedModifiers.contains(pw->m_dmabufParams->modifier))) {
if (modifierProperty && (!m_dmabufParams || !receivedModifiers.contains(m_dmabufParams->modifier))) {
if (modifierProperty->flags & SPA_POD_PROP_FLAG_DONT_FIXATE) {
// DRM_MOD_INVALID should be used as a last option. Do not just remove it it's the only
// item on the list
if (receivedModifiers.count() > 1) {
receivedModifiers.removeAll(DRM_FORMAT_MOD_INVALID);
}
pw->m_dmabufParams = kwinApp()->outputBackend()->testCreateDmaBuf(pw->m_resolution, pw->m_drmFormat, receivedModifiers);
m_dmabufParams = kwinApp()->outputBackend()->testCreateDmaBuf(m_resolution, m_drmFormat, receivedModifiers);
} else {
pw->m_dmabufParams = kwinApp()->outputBackend()->testCreateDmaBuf(pw->m_resolution, pw->m_drmFormat, {DRM_FORMAT_MOD_INVALID});
m_dmabufParams = kwinApp()->outputBackend()->testCreateDmaBuf(m_resolution, m_drmFormat, {DRM_FORMAT_MOD_INVALID});
}
// In case we fail to use any modifier from the list of offered ones, remove these
// from our all future offerings, otherwise there will be no indication that it cannot
// be used and clients can go for it over and over
if (!pw->m_dmabufParams.has_value()) {
if (!m_dmabufParams.has_value()) {
for (uint64_t modifier : receivedModifiers) {
pw->m_modifiers.removeAll(modifier);
m_modifiers.removeAll(modifier);
}
// Also in case DRM_FORMAT_MOD_INVALID was used and didn't fail, we still need to
// set it as our modifier, otherwise it would be set to default value (0) which is
// also a valid modifier, but not the one we want to actually use
} else if (receivedModifiers.count() == 1 && receivedModifiers.constFirst() == DRM_FORMAT_MOD_INVALID) {
pw->m_dmabufParams->modifier = DRM_FORMAT_MOD_INVALID;
m_dmabufParams->modifier = DRM_FORMAT_MOD_INVALID;
}
qCDebug(KWIN_SCREENCAST) << "Stream dmabuf modifiers received, offering our best suited modifier" << pw->m_dmabufParams.has_value();
qCDebug(KWIN_SCREENCAST) << "Stream dmabuf modifiers received, offering our best suited modifier" << m_dmabufParams.has_value();
char buffer[2048];
auto params = pw->buildFormats(pw->m_dmabufParams.has_value(), buffer);
pw_stream_update_params(pw->m_pwStream, params.data(), params.count());
auto params = buildFormats(m_dmabufParams.has_value(), buffer);
pw_stream_update_params(m_pwStream, params.data(), params.count());
return;
}
qCDebug(KWIN_SCREENCAST) << "Stream format found, defining buffers";
pw->newStreamParams();
newStreamParams();
}
void ScreenCastStream::onStreamAddBuffer(void *data, pw_buffer *buffer)
void ScreenCastStream::onStreamAddBuffer(pw_buffer *buffer)
{
ScreenCastStream *stream = static_cast<ScreenCastStream *>(data);
struct spa_data *spa_data = buffer->buffer->datas;
spa_data->mapoffset = 0;
@ -222,12 +219,12 @@ void ScreenCastStream::onStreamAddBuffer(void *data, pw_buffer *buffer)
std::shared_ptr<DmaBufTexture> dmabuff;
if (spa_data[0].type != SPA_ID_INVALID && spa_data[0].type & (1 << SPA_DATA_DmaBuf)) {
Q_ASSERT(stream->m_dmabufParams);
dmabuff = kwinApp()->outputBackend()->createDmaBufTexture(*stream->m_dmabufParams);
Q_ASSERT(m_dmabufParams);
dmabuff = kwinApp()->outputBackend()->createDmaBufTexture(*m_dmabufParams);
}
if (dmabuff) {
spa_data->maxsize = dmabuff->attributes().pitch[0] * stream->m_resolution.height();
spa_data->maxsize = dmabuff->attributes().pitch[0] * m_resolution.height();
const DmaBufAttributes &dmabufAttribs = dmabuff->attributes();
Q_ASSERT(buffer->buffer->n_datas >= uint(dmabufAttribs.planeCount));
@ -236,7 +233,7 @@ void ScreenCastStream::onStreamAddBuffer(void *data, pw_buffer *buffer)
buffer->buffer->datas[i].fd = dmabufAttribs.fd[i].get();
buffer->buffer->datas[i].data = nullptr;
}
stream->m_dmabufDataForPwBuffer.insert(buffer, dmabuff);
m_dmabufDataForPwBuffer.insert(buffer, dmabuff);
#ifdef F_SEAL_SEAL // Disable memfd on systems that don't have it, like BSD < 12
} else {
if (!(spa_data[0].type & (1 << SPA_DATA_MemFd))) {
@ -244,9 +241,9 @@ void ScreenCastStream::onStreamAddBuffer(void *data, pw_buffer *buffer)
return;
}
const int bytesPerPixel = stream->m_source->hasAlphaChannel() ? 4 : 3;
const int stride = SPA_ROUND_UP_N(stream->m_resolution.width() * bytesPerPixel, 4);
spa_data->maxsize = stride * stream->m_resolution.height();
const int bytesPerPixel = m_source->hasAlphaChannel() ? 4 : 3;
const int stride = SPA_ROUND_UP_N(m_resolution.width() * bytesPerPixel, 4);
spa_data->maxsize = stride * m_resolution.height();
spa_data->type = SPA_DATA_MemFd;
spa_data->fd = memfd_create("kwin-screencast-memfd", MFD_CLOEXEC | MFD_ALLOW_SEALING);
if (spa_data->fd == -1) {
@ -279,13 +276,12 @@ void ScreenCastStream::onStreamAddBuffer(void *data, pw_buffer *buffer)
#endif
}
stream->m_waitForNewBuffers = false;
m_waitForNewBuffers = false;
}
void ScreenCastStream::onStreamRemoveBuffer(void *data, pw_buffer *buffer)
void ScreenCastStream::onStreamRemoveBuffer(pw_buffer *buffer)
{
ScreenCastStream *stream = static_cast<ScreenCastStream *>(data);
stream->m_dmabufDataForPwBuffer.remove(buffer);
m_dmabufDataForPwBuffer.remove(buffer);
struct spa_buffer *spa_buffer = buffer->buffer;
struct spa_data *spa_data = spa_buffer->datas;
@ -299,14 +295,12 @@ void ScreenCastStream::onStreamRemoveBuffer(void *data, pw_buffer *buffer)
}
}
void ScreenCastStream::onStreamRenegotiateFormat(void *data, uint64_t)
void ScreenCastStream::onStreamRenegotiateFormat(uint64_t)
{
ScreenCastStream *stream = static_cast<ScreenCastStream *>(data);
stream->m_streaming = false; // pause streaming as we wait for the renegotiation
m_streaming = false; // pause streaming as we wait for the renegotiation
char buffer[2048];
auto params = stream->buildFormats(stream->m_dmabufParams.has_value(), buffer);
pw_stream_update_params(stream->m_pwStream, params.data(), params.count());
auto params = buildFormats(m_dmabufParams.has_value(), buffer);
pw_stream_update_params(m_pwStream, params.data(), params.count());
}
ScreenCastStream::ScreenCastStream(ScreenCastSource *source, QObject *parent)
@ -320,10 +314,22 @@ ScreenCastStream::ScreenCastStream(ScreenCastSource *source, QObject *parent)
});
m_pwStreamEvents.version = PW_VERSION_STREAM_EVENTS;
m_pwStreamEvents.add_buffer = &ScreenCastStream::onStreamAddBuffer;
m_pwStreamEvents.remove_buffer = &ScreenCastStream::onStreamRemoveBuffer;
m_pwStreamEvents.state_changed = &ScreenCastStream::onStreamStateChanged;
m_pwStreamEvents.param_changed = &ScreenCastStream::onStreamParamChanged;
m_pwStreamEvents.add_buffer = [](void *data, struct pw_buffer *buffer) {
auto _this = static_cast<ScreenCastStream *>(data);
_this->onStreamAddBuffer(buffer);
};
m_pwStreamEvents.remove_buffer = [](void *data, struct pw_buffer *buffer) {
auto _this = static_cast<ScreenCastStream *>(data);
_this->onStreamRemoveBuffer(buffer);
};
m_pwStreamEvents.state_changed = [](void *data, pw_stream_state old, pw_stream_state state, const char *error_message) {
auto _this = static_cast<ScreenCastStream *>(data);
_this->onStreamStateChanged(old, state, error_message);
};
m_pwStreamEvents.param_changed = [](void *data, uint32_t id, const struct spa_pod *param) {
auto _this = static_cast<ScreenCastStream *>(data);
_this->onStreamParamChanged(id, param);
};
connect(&m_pendingFrame, &QTimer::timeout, this, [this] {
recordFrame(m_pendingDamages);
@ -354,7 +360,12 @@ bool ScreenCastStream::init()
return false;
}
m_pwRenegotiate = pw_loop_add_event(m_pwCore->pwMainLoop, onStreamRenegotiateFormat, this);
m_pwRenegotiate = pw_loop_add_event(
m_pwCore->pwMainLoop, [](void *data, uint64_t format) {
auto _this = static_cast<ScreenCastStream *>(data);
_this->onStreamRenegotiateFormat(format);
},
this);
return true;
}

@ -74,11 +74,11 @@ Q_SIGNALS:
void stopStreaming();
private:
static void onStreamParamChanged(void *data, uint32_t id, const struct spa_pod *format);
static void onStreamStateChanged(void *data, pw_stream_state old, pw_stream_state state, const char *error_message);
static void onStreamAddBuffer(void *data, pw_buffer *buffer);
static void onStreamRemoveBuffer(void *data, pw_buffer *buffer);
static void onStreamRenegotiateFormat(void *data, uint64_t);
void onStreamParamChanged(uint32_t id, const struct spa_pod *format);
void onStreamStateChanged(pw_stream_state old, pw_stream_state state, const char *error_message);
void onStreamAddBuffer(pw_buffer *buffer);
void onStreamRemoveBuffer(pw_buffer *buffer);
void onStreamRenegotiateFormat(uint64_t);
bool createStream();
QVector<const spa_pod *> buildFormats(bool fixate, char buffer[2048]);

Loading…
Cancel
Save