diff --git a/src/gst/gstpipewirepool.c b/src/gst/gstpipewirepool.c index 78869e163..f00612fc8 100644 --- a/src/gst/gstpipewirepool.c +++ b/src/gst/gstpipewirepool.c @@ -94,13 +94,21 @@ void gst_pipewire_pool_wrap_buffer (GstPipeWirePool *pool, struct pw_buffer *b) } if (pool->add_metavideo) { - gst_buffer_add_video_meta_full (buf, GST_VIDEO_FRAME_FLAG_NONE, + GstVideoMeta *meta = gst_buffer_add_video_meta_full (buf, + GST_VIDEO_FRAME_FLAG_NONE, GST_VIDEO_INFO_FORMAT (&pool->video_info), GST_VIDEO_INFO_WIDTH (&pool->video_info), GST_VIDEO_INFO_HEIGHT (&pool->video_info), GST_VIDEO_INFO_N_PLANES (&pool->video_info), pool->video_info.offset, pool->video_info.stride); + + /* + * We need to set the video meta as pooled, else gst_buffer_pool_release_buffer + * will call reset_buffer and the default_reset_buffer implementation for + * GstBufferPool removes all metadata without the POOLED flag. + */ + GST_META_FLAG_SET (meta, GST_META_FLAG_POOLED); } data->pool = gst_object_ref (pool); diff --git a/src/gst/gstpipewiresink.c b/src/gst/gstpipewiresink.c index aa9d94b99..7f32f0fa8 100644 --- a/src/gst/gstpipewiresink.c +++ b/src/gst/gstpipewiresink.c @@ -314,6 +314,10 @@ gst_pipewire_sink_update_params (GstPipeWireSink *sink) spa_pod_builder_add (&b, SPA_PARAM_BUFFERS_size, SPA_POD_CHOICE_RANGE_Int(size, size, INT32_MAX), 0); + /* MUST have n_datas == n_planes */ + spa_pod_builder_add (&b, + SPA_PARAM_BUFFERS_blocks, + SPA_POD_Int(GST_VIDEO_INFO_N_PLANES (&pool->video_info))); spa_pod_builder_add (&b, SPA_PARAM_BUFFERS_stride, SPA_POD_CHOICE_RANGE_Int(0, 0, INT32_MAX), @@ -630,6 +634,9 @@ do_send_buffer (GstPipeWireSink *pwsink, GstBuffer *buffer) } } data->b->size = 0; + + spa_assert(b->n_datas == gst_buffer_n_memory(buffer)); + for (i = 0; i < b->n_datas; i++) { struct spa_data *d = &b->datas[i]; GstMemory *mem = gst_buffer_peek_memory (buffer, i); @@ -643,16 +650,24 @@ do_send_buffer (GstPipeWireSink *pwsink, GstBuffer *buffer) GstVideoMeta *meta = gst_buffer_get_video_meta (buffer); if (meta) { if (meta->n_planes == b->n_datas) { + uint32_t n_planes = GST_VIDEO_INFO_N_PLANES (&data->pool->video_info); + gboolean is_planar = n_planes > 1; gsize video_size = 0; - for (i = 0; i < meta->n_planes; i++) { + + for (i = 0; i < n_planes; i++) { struct spa_data *d = &b->datas[i]; - d->chunk->offset += meta->offset[i] - video_size; + d->chunk->stride = meta->stride[i]; + if (is_planar) + d->chunk->offset = meta->offset[i]; + else + d->chunk->offset += meta->offset[i] - video_size; video_size += d->chunk->size; } } else { - GST_ERROR_OBJECT (pwsink, "plane num not matching, meta:%u buffer:%u", meta->n_planes, b->n_datas); + GST_ERROR_OBJECT (pwsink, "plane num not matching, meta:%u buffer:%u", + meta->n_planes, b->n_datas); } } diff --git a/src/gst/gstpipewiresrc.c b/src/gst/gstpipewiresrc.c index 1cd049418..c9a5d43cd 100644 --- a/src/gst/gstpipewiresrc.c +++ b/src/gst/gstpipewiresrc.c @@ -661,8 +661,12 @@ static GstBuffer *dequeue_buffer(GstPipeWireSrc *pwsrc) } if (pwsrc->is_video) { - gsize video_size = 0; GstVideoInfo *info = &pwsrc->video_info; + uint32_t n_datas = b->buffer->n_datas; + uint32_t n_planes = GST_VIDEO_INFO_N_PLANES (info); + gboolean is_planar = n_planes > 1; + gsize video_size = 0; + GstVideoMeta *meta = gst_buffer_add_video_meta_full (buf, GST_VIDEO_FRAME_FLAG_NONE, GST_VIDEO_INFO_FORMAT (info), GST_VIDEO_INFO_WIDTH (info), @@ -671,15 +675,19 @@ static GstBuffer *dequeue_buffer(GstPipeWireSrc *pwsrc) info->offset, info->stride); - for (i = 0; i < MIN (b->buffer->n_datas, GST_VIDEO_MAX_PLANES); i++) { + for (i = 0; i < MIN (n_datas, n_planes); i++) { struct spa_data *d = &b->buffer->datas[i]; - meta->offset[i] = video_size; + meta->offset[i] = is_planar ? d->chunk->offset : video_size; meta->stride[i] = d->chunk->stride; video_size += d->chunk->size; } } + if (b->buffer->n_datas != gst_buffer_n_memory(data->buf)) { + GST_ERROR_OBJECT(pwsrc, "n_datas != n_memory"); + } + for (i = 0; i < b->buffer->n_datas; i++) { struct spa_data *d = &b->buffer->datas[i];