It turned out that the last diff didn't work out so well.
Depending on the resolution it could happen that uvideo just could
allocate enough memory for the buffers, but xhci didn't had enough
left to allocate the ring buffers.
What worked out best for me is to limit the max. buffers to 8.
I still can capture 1920x1080 (H.264) with constantly 30fps with
this.
If I don't hear back about any concerns in the next few days,
I would commit the following diff.
Index: uvideo.h
===
RCS file: /cvs/src/sys/dev/usb/uvideo.h,v
retrieving revision 1.59
diff -u -p -u -p -r1.59 uvideo.h
--- uvideo.h7 Aug 2019 11:14:16 - 1.59
+++ uvideo.h2 Dec 2019 06:43:53 -
@@ -455,7 +455,7 @@ struct uvideo_frame_buffer {
uint32_t fmt_flags;
};
-#define UVIDEO_MAX_BUFFERS 32
+#define UVIDEO_MAX_BUFFERS 8
struct uvideo_mmap {
SIMPLEQ_ENTRY(uvideo_mmap) q_frames;
uint8_t *buf;
On Sat, Nov 23, 2019 at 09:13:05AM +0100, Marcus Glocker wrote:
> Some video apps like ffmpeg are quite aggressive in requesting stream
> buffers from the driver. E.g. when I want to record 1920x1080 with
> ffmpeg and my Logitech Webcam C930e, ffmpeg will request 256 buffers
> via VIDIOC_REQBUFS which we will limit to 32 first, but still will end
> up in a ~132MB (!) malloc request - Which finally fails.
>
> Instead of just hard aborting in that case, the following diff will try
> to decrease the buffers by a quarter until we are low enough to malloc
> the memory.
>
> This makes 1920x1080 work for me finally with 8 buffers, which is still
> high enough IMO.
>
> OK?
>
>
> Index: uvideo.c
> ===
> RCS file: /cvs/src/sys/dev/usb/uvideo.c,v
> retrieving revision 1.205
> diff -u -p -u -p -r1.205 uvideo.c
> --- uvideo.c 14 Oct 2019 09:20:48 - 1.205
> +++ uvideo.c 23 Nov 2019 07:49:09 -
> @@ -3294,12 +3294,15 @@ uvideo_reqbufs(void *v, struct v4l2_requ
> sc->sc_mmap_count = 0;
> return (EINVAL);
> }
> - buf_size_total = sc->sc_mmap_count * buf_size;
> - buf_size_total = round_page(buf_size_total); /* page align buffer */
> - sc->sc_mmap_buffer = malloc(buf_size_total, M_DEVBUF, M_NOWAIT);
> + while (sc->sc_mmap_count > 0) {
> + buf_size_total = round_page(sc->sc_mmap_count * buf_size);
> + sc->sc_mmap_buffer = malloc(buf_size_total, M_DEVBUF, M_NOWAIT);
> + if (sc->sc_mmap_buffer != NULL)
> + break;
> + sc->sc_mmap_count = sc->sc_mmap_count / 4;
> + }
> if (sc->sc_mmap_buffer == NULL) {
> printf("%s: can't allocate mmap buffer!\n", DEVNAME(sc));
> - sc->sc_mmap_count = 0;
> return (EINVAL);
> }
> sc->sc_mmap_buffer_size = buf_size_total;
>