mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-29 05:40:27 -04:00
gst: handle blocks and size allocation for encoded format
In case of encoded video we get n_planes as 0 from the video info so passing that as n_datas is failing during the buffer negotiation. Make sure to use an appropriate value based on whether we have raw video or not. Co-authored-by: Taruntej Kanakamalla <taruntej@asymptotic.io>
This commit is contained in:
parent
55f71520db
commit
ebe9381236
6 changed files with 65 additions and 15 deletions
|
|
@ -66,7 +66,10 @@ void gst_pipewire_pool_wrap_buffer (GstPipeWirePool *pool, struct pw_buffer *b)
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
GstPipeWirePoolData *data;
|
GstPipeWirePoolData *data;
|
||||||
/* Default to a large enough value */
|
/* Default to a large enough value */
|
||||||
gsize plane_sizes[GST_VIDEO_MAX_PLANES] = { pool->video_info.size, };
|
gsize plane_0_size = pool->has_rawvideo ?
|
||||||
|
pool->video_info.size :
|
||||||
|
(gsize) pool->video_info.width * pool->video_info.height;
|
||||||
|
gsize plane_sizes[GST_VIDEO_MAX_PLANES] = { plane_0_size, };
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (pool, "wrap buffer, datas:%d", b->buffer->n_datas);
|
GST_DEBUG_OBJECT (pool, "wrap buffer, datas:%d", b->buffer->n_datas);
|
||||||
|
|
||||||
|
|
@ -333,11 +336,20 @@ set_config (GstBufferPool * pool, GstStructure * config)
|
||||||
if (g_str_has_prefix (gst_structure_get_name (structure), "video/") ||
|
if (g_str_has_prefix (gst_structure_get_name (structure), "video/") ||
|
||||||
g_str_has_prefix (gst_structure_get_name (structure), "image/")) {
|
g_str_has_prefix (gst_structure_get_name (structure), "image/")) {
|
||||||
p->has_video = TRUE;
|
p->has_video = TRUE;
|
||||||
|
|
||||||
gst_video_info_from_caps (&p->video_info, caps);
|
gst_video_info_from_caps (&p->video_info, caps);
|
||||||
|
|
||||||
|
if (GST_VIDEO_FORMAT_INFO_IS_VALID_RAW (p->video_info.finfo)
|
||||||
|
#ifdef HAVE_GSTREAMER_DMA_DRM
|
||||||
|
&& GST_VIDEO_FORMAT_INFO_FORMAT (p->video_info.finfo) != GST_VIDEO_FORMAT_DMA_DRM
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
p->has_rawvideo = TRUE;
|
||||||
|
else
|
||||||
|
p->has_rawvideo = FALSE;
|
||||||
|
|
||||||
#ifdef HAVE_GSTREAMER_SHM_ALLOCATOR
|
#ifdef HAVE_GSTREAMER_SHM_ALLOCATOR
|
||||||
if (GST_VIDEO_FORMAT_INFO_IS_VALID_RAW (p->video_info.finfo) &&
|
if (p->has_rawvideo) {
|
||||||
GST_VIDEO_FORMAT_INFO_FORMAT (p->video_info.finfo) != GST_VIDEO_FORMAT_DMA_DRM) {
|
|
||||||
gst_video_alignment_reset (&p->video_align);
|
gst_video_alignment_reset (&p->video_align);
|
||||||
gst_video_info_align (&p->video_info, &p->video_align);
|
gst_video_info_align (&p->video_info, &p->video_align);
|
||||||
}
|
}
|
||||||
|
|
@ -349,11 +361,11 @@ set_config (GstBufferPool * pool, GstStructure * config)
|
||||||
g_assert_not_reached ();
|
g_assert_not_reached ();
|
||||||
}
|
}
|
||||||
|
|
||||||
p->add_metavideo = p->has_video && gst_buffer_pool_config_has_option (config,
|
p->add_metavideo = p->has_rawvideo && gst_buffer_pool_config_has_option (config,
|
||||||
GST_BUFFER_POOL_OPTION_VIDEO_META);
|
GST_BUFFER_POOL_OPTION_VIDEO_META);
|
||||||
|
|
||||||
#ifdef HAVE_GSTREAMER_SHM_ALLOCATOR
|
#ifdef HAVE_GSTREAMER_SHM_ALLOCATOR
|
||||||
has_videoalign = p->has_video && gst_buffer_pool_config_has_option (config,
|
has_videoalign = p->has_rawvideo && gst_buffer_pool_config_has_option (config,
|
||||||
GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT);
|
GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT);
|
||||||
|
|
||||||
if (has_videoalign) {
|
if (has_videoalign) {
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,12 @@ G_DECLARE_FINAL_TYPE (GstPipeWirePool, gst_pipewire_pool, GST, PIPEWIRE_POOL, Gs
|
||||||
#define PIPEWIRE_POOL_MIN_BUFFERS 2u
|
#define PIPEWIRE_POOL_MIN_BUFFERS 2u
|
||||||
#define PIPEWIRE_POOL_MAX_BUFFERS 16u
|
#define PIPEWIRE_POOL_MAX_BUFFERS 16u
|
||||||
|
|
||||||
|
/* Only available in GStreamer 1.22+ */
|
||||||
|
#ifndef GST_VIDEO_FORMAT_INFO_IS_VALID_RAW
|
||||||
|
#define GST_VIDEO_FORMAT_INFO_IS_VALID_RAW(info) \
|
||||||
|
(info != NULL && (info)->format > GST_VIDEO_FORMAT_ENCODED)
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct _GstPipeWirePoolData GstPipeWirePoolData;
|
typedef struct _GstPipeWirePoolData GstPipeWirePoolData;
|
||||||
struct _GstPipeWirePoolData {
|
struct _GstPipeWirePoolData {
|
||||||
GstPipeWirePool *pool;
|
GstPipeWirePool *pool;
|
||||||
|
|
@ -42,6 +48,7 @@ struct _GstPipeWirePool {
|
||||||
guint n_buffers;
|
guint n_buffers;
|
||||||
|
|
||||||
gboolean has_video;
|
gboolean has_video;
|
||||||
|
gboolean has_rawvideo;
|
||||||
gboolean add_metavideo;
|
gboolean add_metavideo;
|
||||||
GstAudioInfo audio_info;
|
GstAudioInfo audio_info;
|
||||||
GstVideoInfo video_info;
|
GstVideoInfo video_info;
|
||||||
|
|
|
||||||
|
|
@ -321,11 +321,18 @@ gst_pipewire_sink_update_params (GstPipeWireSink *sink)
|
||||||
spa_pod_builder_add (&b,
|
spa_pod_builder_add (&b,
|
||||||
SPA_PARAM_BUFFERS_size, SPA_POD_CHOICE_RANGE_Int(size, size, INT32_MAX),
|
SPA_PARAM_BUFFERS_size, SPA_POD_CHOICE_RANGE_Int(size, size, INT32_MAX),
|
||||||
0);
|
0);
|
||||||
if (sink->is_video) {
|
if (sink->is_rawvideo) {
|
||||||
/* MUST have n_datas == n_planes */
|
/* MUST have n_datas == n_planes */
|
||||||
spa_pod_builder_add (&b,
|
spa_pod_builder_add (&b,
|
||||||
SPA_PARAM_BUFFERS_blocks,
|
SPA_PARAM_BUFFERS_blocks,
|
||||||
SPA_POD_Int(GST_VIDEO_INFO_N_PLANES (&pool->video_info)), 0);
|
SPA_POD_Int(GST_VIDEO_INFO_N_PLANES (&pool->video_info)),
|
||||||
|
0);
|
||||||
|
} else {
|
||||||
|
/* Non-planar data, get a single block */
|
||||||
|
spa_pod_builder_add (&b,
|
||||||
|
SPA_PARAM_BUFFERS_blocks,
|
||||||
|
SPA_POD_Int(1),
|
||||||
|
0);
|
||||||
}
|
}
|
||||||
|
|
||||||
spa_pod_builder_add (&b,
|
spa_pod_builder_add (&b,
|
||||||
|
|
@ -343,7 +350,7 @@ gst_pipewire_sink_update_params (GstPipeWireSink *sink)
|
||||||
SPA_PARAM_META_type, SPA_POD_Id(SPA_META_Header),
|
SPA_PARAM_META_type, SPA_POD_Id(SPA_META_Header),
|
||||||
SPA_PARAM_META_size, SPA_POD_Int(sizeof (struct spa_meta_header)));
|
SPA_PARAM_META_size, SPA_POD_Int(sizeof (struct spa_meta_header)));
|
||||||
|
|
||||||
if (sink->is_video) {
|
if (sink->is_rawvideo) {
|
||||||
port_params[n_params++] = spa_pod_builder_add_object (&b,
|
port_params[n_params++] = spa_pod_builder_add_object (&b,
|
||||||
SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta,
|
SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta,
|
||||||
SPA_PARAM_META_type, SPA_POD_Id(SPA_META_VideoCrop),
|
SPA_PARAM_META_type, SPA_POD_Id(SPA_META_VideoCrop),
|
||||||
|
|
@ -369,7 +376,7 @@ gst_pipewire_sink_init (GstPipeWireSink * sink)
|
||||||
|
|
||||||
sink->mode = DEFAULT_PROP_MODE;
|
sink->mode = DEFAULT_PROP_MODE;
|
||||||
sink->use_bufferpool = DEFAULT_PROP_USE_BUFFERPOOL;
|
sink->use_bufferpool = DEFAULT_PROP_USE_BUFFERPOOL;
|
||||||
sink->is_video = false;
|
sink->is_rawvideo = false;
|
||||||
|
|
||||||
GST_OBJECT_FLAG_SET (sink, GST_ELEMENT_FLAG_PROVIDE_CLOCK);
|
GST_OBJECT_FLAG_SET (sink, GST_ELEMENT_FLAG_PROVIDE_CLOCK);
|
||||||
|
|
||||||
|
|
@ -387,7 +394,7 @@ gst_pipewire_sink_sink_fixate (GstBaseSink * bsink, GstCaps * caps)
|
||||||
structure = gst_caps_get_structure (caps, 0);
|
structure = gst_caps_get_structure (caps, 0);
|
||||||
|
|
||||||
if (gst_structure_has_name (structure, "video/x-raw")) {
|
if (gst_structure_has_name (structure, "video/x-raw")) {
|
||||||
pwsink->is_video = true;
|
pwsink->is_rawvideo = true;
|
||||||
gst_structure_fixate_field_nearest_int (structure, "width", 320);
|
gst_structure_fixate_field_nearest_int (structure, "width", 320);
|
||||||
gst_structure_fixate_field_nearest_int (structure, "height", 240);
|
gst_structure_fixate_field_nearest_int (structure, "height", 240);
|
||||||
gst_structure_fixate_field_nearest_fraction (structure, "framerate", 30, 1);
|
gst_structure_fixate_field_nearest_fraction (structure, "framerate", 30, 1);
|
||||||
|
|
@ -779,9 +786,21 @@ gst_pipewire_sink_setcaps (GstBaseSink * bsink, GstCaps * caps)
|
||||||
if (pwsink->use_bufferpool != USE_BUFFERPOOL_YES)
|
if (pwsink->use_bufferpool != USE_BUFFERPOOL_YES)
|
||||||
pwsink->use_bufferpool = USE_BUFFERPOOL_NO;
|
pwsink->use_bufferpool = USE_BUFFERPOOL_NO;
|
||||||
} else {
|
} else {
|
||||||
|
GstVideoInfo video_info;
|
||||||
|
|
||||||
pwsink->rate = rate = 0;
|
pwsink->rate = rate = 0;
|
||||||
pwsink->rate_match = false;
|
pwsink->rate_match = false;
|
||||||
pwsink->is_video = true;
|
|
||||||
|
gst_video_info_from_caps (&video_info, caps);
|
||||||
|
|
||||||
|
if (GST_VIDEO_FORMAT_INFO_IS_VALID_RAW (video_info.finfo)
|
||||||
|
#ifdef HAVE_GSTREAMER_DMA_DRM
|
||||||
|
&& GST_VIDEO_FORMAT_INFO_FORMAT (video_info.finfo) != GST_VIDEO_FORMAT_DMA_DRM
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
pwsink->is_rawvideo = TRUE;
|
||||||
|
else
|
||||||
|
pwsink->is_rawvideo = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
spa_dll_set_bw(&pwsink->stream->dll, SPA_DLL_BW_MIN, 4096, rate);
|
spa_dll_set_bw(&pwsink->stream->dll, SPA_DLL_BW_MIN, 4096, rate);
|
||||||
|
|
@ -866,7 +885,7 @@ gst_pipewire_sink_setcaps (GstBaseSink * bsink, GstCaps * caps)
|
||||||
config = gst_buffer_pool_get_config (GST_BUFFER_POOL_CAST (pwsink->stream->pool));
|
config = gst_buffer_pool_get_config (GST_BUFFER_POOL_CAST (pwsink->stream->pool));
|
||||||
gst_buffer_pool_config_get_params (config, NULL, &size, &min_buffers, &max_buffers);
|
gst_buffer_pool_config_get_params (config, NULL, &size, &min_buffers, &max_buffers);
|
||||||
gst_buffer_pool_config_set_params (config, caps, size, min_buffers, max_buffers);
|
gst_buffer_pool_config_set_params (config, caps, size, min_buffers, max_buffers);
|
||||||
if (pwsink->is_video) {
|
if (pwsink->is_rawvideo) {
|
||||||
gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
|
gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
|
||||||
#ifdef HAVE_GSTREAMER_SHM_ALLOCATOR
|
#ifdef HAVE_GSTREAMER_SHM_ALLOCATOR
|
||||||
gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT);
|
gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT);
|
||||||
|
|
@ -953,7 +972,7 @@ gst_pipewire_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
|
||||||
if (res != GST_FLOW_OK)
|
if (res != GST_FLOW_OK)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
if (pwsink->is_video) {
|
if (pwsink->is_rawvideo) {
|
||||||
GstVideoFrame src, dst;
|
GstVideoFrame src, dst;
|
||||||
gboolean copied = FALSE;
|
gboolean copied = FALSE;
|
||||||
buf_size = 0; // to break from the loop
|
buf_size = 0; // to break from the loop
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ struct _GstPipeWireSink {
|
||||||
gboolean negotiated;
|
gboolean negotiated;
|
||||||
gboolean rate_match;
|
gboolean rate_match;
|
||||||
gint rate;
|
gint rate;
|
||||||
gboolean is_video;
|
gboolean is_rawvideo;
|
||||||
|
|
||||||
GstPipeWireSinkMode mode;
|
GstPipeWireSinkMode mode;
|
||||||
GstPipeWireSinkSlaveMethod slave_method;
|
GstPipeWireSinkSlaveMethod slave_method;
|
||||||
|
|
|
||||||
|
|
@ -777,7 +777,7 @@ static GstBuffer *dequeue_buffer(GstPipeWireSrc *pwsrc)
|
||||||
pwsrc->transform_value = transform_value;
|
pwsrc->transform_value = transform_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pwsrc->is_video) {
|
if (pwsrc->is_rawvideo) {
|
||||||
GstVideoInfo *info = &pwsrc->video_info;
|
GstVideoInfo *info = &pwsrc->video_info;
|
||||||
uint32_t n_datas = b->buffer->n_datas;
|
uint32_t n_datas = b->buffer->n_datas;
|
||||||
uint32_t n_planes = GST_VIDEO_INFO_N_PLANES (info);
|
uint32_t n_planes = GST_VIDEO_INFO_N_PLANES (info);
|
||||||
|
|
@ -1285,6 +1285,16 @@ handle_format_change (GstPipeWireSrc *pwsrc,
|
||||||
gst_video_info_dma_drm_init (&pwsrc->drm_info);
|
gst_video_info_dma_drm_init (&pwsrc->drm_info);
|
||||||
#endif
|
#endif
|
||||||
gst_video_info_from_caps (&pwsrc->video_info, pwsrc->caps);
|
gst_video_info_from_caps (&pwsrc->video_info, pwsrc->caps);
|
||||||
|
|
||||||
|
if (GST_VIDEO_FORMAT_INFO_IS_VALID_RAW (pwsrc->video_info.finfo)
|
||||||
|
#ifdef HAVE_GSTREAMER_DMA_DRM
|
||||||
|
&& GST_VIDEO_FORMAT_INFO_FORMAT (pwsrc->video_info.finfo) != GST_VIDEO_FORMAT_DMA_DRM
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
pwsrc->is_rawvideo = TRUE;
|
||||||
|
else
|
||||||
|
pwsrc->is_rawvideo = FALSE;
|
||||||
|
|
||||||
#ifdef HAVE_GSTREAMER_DMA_DRM
|
#ifdef HAVE_GSTREAMER_DMA_DRM
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -1297,6 +1307,7 @@ handle_format_change (GstPipeWireSrc *pwsrc,
|
||||||
} else {
|
} else {
|
||||||
pwsrc->negotiated = FALSE;
|
pwsrc->negotiated = FALSE;
|
||||||
pwsrc->is_video = FALSE;
|
pwsrc->is_video = FALSE;
|
||||||
|
pwsrc->is_rawvideo = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pwsrc->caps) {
|
if (pwsrc->caps) {
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,7 @@ struct _GstPipeWireSrc {
|
||||||
GstCaps *possible_caps;
|
GstCaps *possible_caps;
|
||||||
|
|
||||||
gboolean is_video;
|
gboolean is_video;
|
||||||
|
gboolean is_rawvideo;
|
||||||
GstVideoInfo video_info;
|
GstVideoInfo video_info;
|
||||||
#ifdef HAVE_GSTREAMER_DMA_DRM
|
#ifdef HAVE_GSTREAMER_DMA_DRM
|
||||||
GstVideoInfoDmaDrm drm_info;
|
GstVideoInfoDmaDrm drm_info;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue