From 98f524bb418c5ec5b202a06496ab3f05116170c2 Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Fri, 21 May 2021 14:41:38 +0200 Subject: [PATCH] qemu-usb/webcam: signal capturing off earlier based on comment in Linux sources. Reduce fallback off-capturing detection to 1s. Issue #4078 --- repos/libports/src/lib/qemu-usb/README | 9 +++++-- repos/libports/src/lib/qemu-usb/dev-webcam.c | 28 +++++++++++++++----- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/repos/libports/src/lib/qemu-usb/README b/repos/libports/src/lib/qemu-usb/README index 03081167fc..2fd540be38 100644 --- a/repos/libports/src/lib/qemu-usb/README +++ b/repos/libports/src/lib/qemu-usb/README @@ -48,8 +48,13 @@ will open and will use a Genode capture session to obtain the frames in the rate as specified by the frame per secondes (fps) attribute. The 'vertical_flip' attribute specifies, whether the frames are shown flipped for guests. For Windows guests the value has to be false, for Linux guests -true. The format supported by the model is in BGR3. If the 'screen_size' is set +true. The format supported by the model is YUV2 or BGR3. If the 'screen_size' is set to true, the webcam model will try to use the screen size as provided by the capture session. If the screen size is invalid (e.g. 0x0), the attribute values of 'width' and 'height' will be used instead. If the 'report' attribute -is set, a report will be generated whenever the guests starts/ends capturing. +is set, a report will be generated whenever the guests starts/ends capturing and +if the capturing format choosen by the guest changes, + + +or + diff --git a/repos/libports/src/lib/qemu-usb/dev-webcam.c b/repos/libports/src/lib/qemu-usb/dev-webcam.c index e4aca89150..002d2f64f1 100644 --- a/repos/libports/src/lib/qemu-usb/dev-webcam.c +++ b/repos/libports/src/lib/qemu-usb/dev-webcam.c @@ -533,10 +533,13 @@ static void webcam_timeout(void *opague) USBDevice *dev = (USBDevice *)opague; USBWebcamState *state = USB_WEBCAM(opague); + if (!state->capture) + return; + if (!state->delayed_packet) { unsigned const fps = 10000000u / formats[active_format()].interval; - /* capture off detection - after 2s or if in delay_packet state */ - if (state->delay_packet || (state->watchdog && state->watchdog >= fps * 2)) { + /* capture off detection - after 1s or if in delay_packet state */ + if (state->delay_packet || (state->watchdog && state->watchdog >= fps)) { state->capture = false; state->delay_packet = false; usb_webcam_capture_state_changed(state->capture); @@ -601,11 +604,24 @@ static void usb_webcam_handle_control(USBDevice * const dev, if (length || (index != (USB_DIR_IN | DEVICE_EP_ID))) break; - /* release packets on feature == 0 endpoint clear request */ - if (!value) { + /* endpoint clear request with feature == 0 */ + if (value == 0) { + /* + * UVC standard does not specify how to signal stopping of capture + * on a bulk endpoint. + * According to comment in Linux, drivers/media/usb/uvc/uvc_video.c + * uvc_video_stop_streaming(), a clear request with feature == 0 + * is used as stop signal as used by Windows. + */ USBWebcamState *state = USB_WEBCAM(dev); - if (state && state->delayed_packet) - state->delayed_packet = 0; + if (state) { + if (state->delayed_packet) + state->delayed_packet = 0; + if (state->capture) { + state->capture = false; + usb_webcam_capture_state_changed(state->capture); + } + } stall = false; } break;