diff options
author | William Manley <will@williammanley.net> | 2016-10-08 18:11:17 +0200 |
---|---|---|
committer | Sebastian Dröge <sebastian@centricular.com> | 2016-11-01 20:12:56 +0200 |
commit | 56b1d088a9a6c69f8c1f3067bc261e88632fae4a (patch) | |
tree | f216954a8e8dd263e72ace42e409d114eaf20943 | |
parent | e0aec317ffc4c26dd9ecaf890e604a10f678afbc (diff) |
v4l2: Warn, don't assert if v4l gives us a buffer with a too large size
I've seen problems where the `bytesused` field of `v4l2_buffer` would be
a silly number causing the later call to:
gst_memory_resize (group->mem[i], 0, group->planes[i].bytesused);
to result in this error to be printed:
(pulsevideo:11): GStreamer-CRITICAL **: gst_memory_resize: assertion 'size + mem->offset + offset <= mem->maxsize' failed
besides causing who-knows what other problems.
We make the assumption that this buffer has still been dequeued correctly
so just clamp to a valid size so downstream elements won't end up in
undefined behaviour.
The invalid `v4l2_buffer` I saw from my capture device was:
buffer = {
index = 0,
type = 1,
bytesused = 534748928, // <- Invalid
flags = 8260, // V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC | V4L2_BUF_FLAG_ERROR | V4L2_BUF_FLAG_DONE
field = 01330, // <- Invalid
timestamp = {
tv_sec = 0,
tv_usec = 0
},
timecode = {
type = 0,
flags = 0,
frames = 0 '\000',
seconds = 0 '\000',
minutes = 0 '\000',
hours = 0 '\000',
userbits = "\000\000\000"
},
sequence = 0,
memory = 2,
m = {
offset = 3537219584,
userptr = 140706665836544, // Could be nonsense, not sure
planes = 0x7ff8d2d5b000,
fd = -757747712
},
length = 2764800,
reserved2 = 0,
reserved = 0
}
This is from gdb with my own annotations added.
This was with gst-plugins-good 1.8.1, a Magewell XI100DUSB-HDMI video
capture device and kernel 3.13 using a dodgy HDMI cable which is great at
breaking HDMI capture devices. I'm using io-mode=userptr and have built
gst-plugins-good without libv4l.
https://bugzilla.gnome.org/show_bug.cgi?id=769765
-rw-r--r-- | sys/v4l2/gstv4l2allocator.c | 11 |
1 files changed, 10 insertions, 1 deletions
diff --git a/sys/v4l2/gstv4l2allocator.c b/sys/v4l2/gstv4l2allocator.c index 923b10f0d..655c2cacc 100644 --- a/sys/v4l2/gstv4l2allocator.c +++ b/sys/v4l2/gstv4l2allocator.c @@ -1327,7 +1327,16 @@ gst_v4l2_allocator_dqbuf (GstV4l2Allocator * allocator, } else { /* for capture, simply read the size */ for (i = 0; i < group->n_mem; i++) { - gst_memory_resize (group->mem[i], 0, group->planes[i].bytesused); + if (G_LIKELY (group->planes[i].bytesused <= group->mem[i]->maxsize)) + gst_memory_resize (group->mem[i], 0, group->planes[i].bytesused); + else { + GST_WARNING_OBJECT (allocator, + "v4l2 provided buffer that is too big for the memory it was " + "writing into. v4l2 claims %" G_GUINT32_FORMAT " bytes used but " + "memory is only %" G_GSIZE_FORMAT "B. This is probably a driver " + "bug.", group->planes[i].bytesused, group->mem[i]->maxsize); + gst_memory_resize (group->mem[i], 0, group->mem[i]->maxsize); + } } } |