gl: bufferpool take into account video stride alignment requirements

when allocating memory. Fixes crashes with avdec_h265 in the AVX2
code path which requires 32-byte stride alignment, but the
GstAllocationParams only specified a 16-byte alignment.

https://bugzilla.gnome.org/show_bug.cgi?id=754120
This commit is contained in:
Tim-Philipp Müller 2015-09-15 11:34:12 +01:00
parent 5adde7f98b
commit 990a49fe4f
2 changed files with 35 additions and 0 deletions

View file

@ -93,6 +93,7 @@ gst_gl_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config)
GstVideoInfo info; GstVideoInfo info;
GstCaps *caps = NULL; GstCaps *caps = NULL;
guint min_buffers, max_buffers; guint min_buffers, max_buffers;
guint max_align, n;
GstAllocator *allocator = NULL; GstAllocator *allocator = NULL;
GstAllocationParams alloc_params; GstAllocationParams alloc_params;
gboolean reset = TRUE; gboolean reset = TRUE;
@ -152,12 +153,21 @@ gst_gl_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config)
priv->want_eglimage = FALSE; priv->want_eglimage = FALSE;
#endif #endif
max_align = alloc_params.align;
if (gst_buffer_pool_config_has_option (config, if (gst_buffer_pool_config_has_option (config,
GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT)) { GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT)) {
priv->add_videometa = TRUE; priv->add_videometa = TRUE;
gst_buffer_pool_config_get_video_alignment (config, &priv->valign); gst_buffer_pool_config_get_video_alignment (config, &priv->valign);
for (n = 0; n < GST_VIDEO_MAX_PLANES; ++n)
max_align |= priv->valign.stride_align[n];
for (n = 0; n < GST_VIDEO_MAX_PLANES; ++n)
priv->valign.stride_align[n] = max_align;
gst_video_info_align (&priv->info, &priv->valign); gst_video_info_align (&priv->info, &priv->valign);
gst_buffer_pool_config_set_video_alignment (config, &priv->valign); gst_buffer_pool_config_set_video_alignment (config, &priv->valign);
@ -165,6 +175,16 @@ gst_gl_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config)
gst_video_alignment_reset (&priv->valign); gst_video_alignment_reset (&priv->valign);
} }
if (alloc_params.align < max_align) {
GST_WARNING_OBJECT (pool, "allocation params alignment %u is smaller "
"than the max specified video stride alignment %u, fixing",
(guint) alloc_params.align, max_align);
alloc_params.align = max_align;
gst_buffer_pool_config_set_allocator (config, allocator, &alloc_params);
priv->params = alloc_params;
}
if (reset) { if (reset) {
if (glpool->upload) if (glpool->upload)
gst_object_unref (glpool->upload); gst_object_unref (glpool->upload);

View file

@ -631,6 +631,21 @@ _gl_mem_init (GstGLMemory * mem, GstAllocator * allocator, GstMemory * parent,
else else
gst_video_alignment_reset (&mem->valign); gst_video_alignment_reset (&mem->valign);
/* double-check alignment requirements (caller should've taken care of this) */
if (params) {
guint max_align, n;
max_align = gst_memory_alignment;
max_align |= params->align;
for (n = 0; n < GST_VIDEO_MAX_PLANES; ++n)
max_align |= mem->valign.stride_align[n];
if (params->align < max_align && max_align > gst_memory_alignment) {
GST_WARNING ("allocation params alignment %" G_GSIZE_FORMAT " is smaller "
"than the max required video alignment %u", params->align, max_align);
}
}
size = gst_gl_get_plane_data_size (info, valign, plane); size = gst_gl_get_plane_data_size (info, valign, plane);
/* we always operate on 2D textures unless we're dealing with wrapped textures */ /* we always operate on 2D textures unless we're dealing with wrapped textures */