pipewire: set CORRUPTED flag when buffer params mismatch

This commit is contained in:
Simon Ser 2021-11-01 14:50:37 +01:00
parent 6be82ccabb
commit 78a2496386

View file

@ -54,13 +54,30 @@ static void request_buffer(struct pipewire_state *state)
return; return;
} }
struct spa_buffer *spa_buffer = pw_buffer->buffer;
struct pipewire_buffer *buffer = (struct pipewire_buffer *) pw_buffer->user_data; struct pipewire_buffer *buffer = (struct pipewire_buffer *) pw_buffer->user_data;
buffer->copying = true;
// Past this exchange, the PipeWire thread shares the buffer with the
// steamcompmgr thread
struct pipewire_buffer *old = out_buffer.exchange(buffer);
assert(old == nullptr);
}
static void copy_buffer(struct pipewire_state *state, struct pipewire_buffer *buffer)
{
std::shared_ptr<CVulkanTexture> tex = std::move(buffer->texture);
assert(tex != nullptr);
assert(tex->m_format == VK_FORMAT_B8G8R8A8_UNORM);
struct pw_buffer *pw_buffer = buffer->buffer;
struct spa_buffer *spa_buffer = pw_buffer->buffer;
bool needs_reneg = buffer->video_info.size.width != tex->m_width || buffer->video_info.size.height != tex->m_height;
struct spa_meta_header *header = (struct spa_meta_header *) spa_buffer_find_meta_data(spa_buffer, SPA_META_Header, sizeof(*header)); struct spa_meta_header *header = (struct spa_meta_header *) spa_buffer_find_meta_data(spa_buffer, SPA_META_Header, sizeof(*header));
if (header != nullptr) { if (header != nullptr) {
header->pts = -1; header->pts = -1;
header->flags = 0; header->flags = needs_reneg ? SPA_META_HEADER_FLAG_CORRUPTED : 0;
header->seq = state->seq++; header->seq = state->seq++;
header->dts_offset = 0; header->dts_offset = 0;
} }
@ -69,13 +86,14 @@ static void request_buffer(struct pipewire_state *state)
chunk->offset = 0; chunk->offset = 0;
chunk->size = state->video_info.size.height * state->stride; chunk->size = state->video_info.size.height * state->stride;
chunk->stride = state->stride; chunk->stride = state->stride;
chunk->flags = needs_reneg ? SPA_CHUNK_FLAG_CORRUPTED : 0;
buffer->copying = true; if (!needs_reneg) {
int bpp = 4;
// Past this exchange, the PipeWire thread shares the buffer with the for (uint32_t i = 0; i < tex->m_height; i++) {
// steamcompmgr thread memcpy(buffer->data + i * buffer->stride, (uint8_t *) tex->m_pMappedData + i * tex->m_unRowPitch, bpp * tex->m_width);
struct pipewire_buffer *old = out_buffer.exchange(buffer); }
assert(old == nullptr); }
} }
static void dispatch_nudge(struct pipewire_state *state, int fd) static void dispatch_nudge(struct pipewire_state *state, int fd)
@ -108,26 +126,9 @@ static void dispatch_nudge(struct pipewire_state *state, int fd)
buffer->copying = false; buffer->copying = false;
{
std::shared_ptr<CVulkanTexture> tex = std::move(buffer->texture);
assert( tex->m_format == VK_FORMAT_B8G8R8A8_UNORM );
if ( buffer->video_info.size.width != tex->m_width || buffer->video_info.size.height != tex->m_height )
{
// Push black frames until the PipeWire thread realizes the stream size has changed
memset( buffer->data, 0, buffer->stride * buffer->video_info.size.height );
}
else
{
int bpp = 4;
for ( unsigned int i = 0; i < tex->m_height; i++ )
{
memcpy( buffer->data + i * buffer->stride, (uint8_t *) tex->m_pMappedData + i * tex->m_unRowPitch, bpp * tex->m_width );
}
}
}
if (buffer->buffer != nullptr) { if (buffer->buffer != nullptr) {
copy_buffer(state, buffer);
int ret = pw_stream_queue_buffer(state->stream, buffer->buffer); int ret = pw_stream_queue_buffer(state->stream, buffer->buffer);
if (ret < 0) { if (ret < 0) {
pwr_log.errorf("pw_stream_queue_buffer failed"); pwr_log.errorf("pw_stream_queue_buffer failed");