xvimagesink: error out on buffer size sanity check failure.

If sanity checks on the buffer size allocated by XvShmCreateImage() fail,
call on g_set_error(), rather than just logging a warning, as this
failure is fatal.

Add a sanity check on buffer size when the video format is RGB. This adds to
existing checks on various YUV pixel formats.

https://bugzilla.gnome.org/show_bug.cgi?id=767712
This commit is contained in:
Duncan Palmer 2016-07-07 22:27:15 +10:00 committed by Tim-Philipp Müller
parent 9834782afa
commit 4e83e894df
3 changed files with 53 additions and 39 deletions

View file

@ -55,6 +55,7 @@ struct _GstXvImageMemory
GstMemory parent; GstMemory parent;
gint im_format; gint im_format;
GstVideoInfo info;
GstVideoRectangle crop; GstVideoRectangle crop;
XvImage *xvimage; XvImage *xvimage;
@ -229,6 +230,7 @@ gst_xvimage_memory_share (GstXvImageMemory * mem, gssize offset, gsize size)
&mem->parent, mem->parent.maxsize, mem->parent.align, &mem->parent, mem->parent.maxsize, mem->parent.align,
mem->parent.offset + offset, size); mem->parent.offset + offset, size);
sub->info = mem->info;
sub->im_format = mem->im_format; sub->im_format = mem->im_format;
sub->crop = mem->crop; sub->crop = mem->crop;
sub->xvimage = mem->xvimage; sub->xvimage = mem->xvimage;
@ -256,8 +258,8 @@ gst_xvimage_memory_copy (GstMemory * gmem, gssize offset, gsize size)
copy = (GstXvImageMemory *) copy = (GstXvImageMemory *)
gst_xvimage_allocator_alloc (GST_XVIMAGE_ALLOCATOR_CAST (gmem->allocator), gst_xvimage_allocator_alloc (GST_XVIMAGE_ALLOCATOR_CAST (gmem->allocator),
mem->im_format, mem->xvimage->width, mem->xvimage->height, &mem->crop, mem->im_format, &mem->info, mem->xvimage->width,
NULL); mem->xvimage->height, &mem->crop, NULL);
memcpy (copy->xvimage->data + copy->parent.offset, memcpy (copy->xvimage->data + copy->parent.offset,
mem->xvimage->data + mem->parent.offset, mem->xvimage->data_size); mem->xvimage->data + mem->parent.offset, mem->xvimage->data_size);
@ -340,20 +342,22 @@ gst_xvimage_allocator_peek_context (GstXvImageAllocator * allocator)
GstMemory * GstMemory *
gst_xvimage_allocator_alloc (GstXvImageAllocator * allocator, gint im_format, gst_xvimage_allocator_alloc (GstXvImageAllocator * allocator, gint im_format,
gint padded_width, gint padded_height, GstVideoRectangle * crop, const GstVideoInfo * info, gint padded_width, gint padded_height,
GError ** error) GstVideoRectangle * crop, GError ** error)
{ {
int (*handler) (Display *, XErrorEvent *); int (*handler) (Display *, XErrorEvent *);
gboolean success = FALSE; gboolean success = FALSE;
GstXvContext *context; GstXvContext *context;
gint align, offset; gint align, offset;
GstXvImageMemory *mem; GstXvImageMemory *mem;
gint expected_size = 0;
context = allocator->context; context = allocator->context;
mem = g_slice_new (GstXvImageMemory); mem = g_slice_new (GstXvImageMemory);
mem->im_format = im_format; mem->im_format = im_format;
mem->info = *info;
#ifdef HAVE_XSHM #ifdef HAVE_XSHM
mem->SHMInfo.shmaddr = ((void *) -1); mem->SHMInfo.shmaddr = ((void *) -1);
mem->SHMInfo.shmid = -1; mem->SHMInfo.shmid = -1;
@ -371,7 +375,6 @@ gst_xvimage_allocator_alloc (GstXvImageAllocator * allocator, gint im_format,
#ifdef HAVE_XSHM #ifdef HAVE_XSHM
if (context->use_xshm) { if (context->use_xshm) {
int expected_size;
mem->xvimage = XvShmCreateImage (context->disp, mem->xvimage = XvShmCreateImage (context->disp,
context->xv_port_id, im_format, NULL, padded_width, padded_height, context->xv_port_id, im_format, NULL, padded_width, padded_height,
@ -401,9 +404,10 @@ gst_xvimage_allocator_alloc (GstXvImageAllocator * allocator, gint im_format,
/* calculate the expected size. This is only for sanity checking the /* calculate the expected size. This is only for sanity checking the
* number we get from X. */ * number we get from X. */
switch (im_format) { if (GST_VIDEO_FORMAT_INFO_IS_YUV (info->finfo)) {
case GST_MAKE_FOURCC ('I', '4', '2', '0'): switch (GST_VIDEO_FORMAT_INFO_FORMAT (info->finfo)) {
case GST_MAKE_FOURCC ('Y', 'V', '1', '2'): case GST_VIDEO_FORMAT_I420:
case GST_VIDEO_FORMAT_YV12:
{ {
gint pitches[3]; gint pitches[3];
gint offsets[3]; gint offsets[3];
@ -427,19 +431,20 @@ gst_xvimage_allocator_alloc (GstXvImageAllocator * allocator, gint im_format,
} }
break; break;
} }
case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'): case GST_VIDEO_FORMAT_YUY2:
case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'): case GST_VIDEO_FORMAT_UYVY:
expected_size = padded_height * GST_ROUND_UP_4 (padded_width * 2); expected_size = padded_height * GST_ROUND_UP_4 (padded_width * 2);
break; break;
default: default:
expected_size = 0;
break; break;
} }
if (expected_size != 0 && mem->xvimage->data_size != expected_size) { } else if (GST_VIDEO_FORMAT_INFO_IS_RGB (info->finfo) &&
GST_WARNING_OBJECT (allocator, GST_VIDEO_FORMAT_INFO_N_PLANES (info->finfo) == 1) {
"unexpected XShm image size (got %d, expected %d)", expected_size = padded_height * GST_ROUND_UP_4 (padded_width *
mem->xvimage->data_size, expected_size); GST_VIDEO_FORMAT_INFO_PSTRIDE (info->finfo, 0));
} }
if (expected_size != 0 && mem->xvimage->data_size != expected_size)
goto unexpected_size;
/* Be verbose about our XvImage stride */ /* Be verbose about our XvImage stride */
{ {
@ -523,6 +528,14 @@ beach:
return GST_MEMORY_CAST (mem); return GST_MEMORY_CAST (mem);
/* ERRORS */ /* ERRORS */
unexpected_size:
{
g_mutex_unlock (&context->lock);
g_set_error (error, GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_WRITE,
"unexpected XShm image size (got %d, expected %d)",
mem->xvimage->data_size, expected_size);
goto beach;
}
create_failed: create_failed:
{ {
g_mutex_unlock (&context->lock); g_mutex_unlock (&context->lock);

View file

@ -44,6 +44,7 @@ GstXvContext * gst_xvimage_allocator_peek_context (GstXvImageAllocator *
GstMemory * gst_xvimage_allocator_alloc (GstXvImageAllocator * allocator, GstMemory * gst_xvimage_allocator_alloc (GstXvImageAllocator * allocator,
gint im_format, gint im_format,
const GstVideoInfo * info,
gint padded_width, gint padded_width,
gint padded_height, gint padded_height,
GstVideoRectangle *crop, GstVideoRectangle *crop,

View file

@ -174,7 +174,7 @@ xvimage_buffer_pool_alloc (GstBufferPool * pool, GstBuffer ** buffer,
xvimage = gst_buffer_new (); xvimage = gst_buffer_new ();
mem = gst_xvimage_allocator_alloc (xvpool->allocator, xvpool->im_format, mem = gst_xvimage_allocator_alloc (xvpool->allocator, xvpool->im_format,
xvpool->padded_width, xvpool->padded_height, &xvpool->crop, &err); info, xvpool->padded_width, xvpool->padded_height, &xvpool->crop, &err);
if (mem == NULL) { if (mem == NULL) {
gst_buffer_unref (xvimage); gst_buffer_unref (xvimage);