def process_webcam_frame(self, device_id, frame_no, encoding, w, h, data): webcam = self.webcam_forwarding_devices.get(device_id) log("process_webcam_frame: device %s, frame no %i: %s %ix%i, %i bytes, webcam=%s", device_id, frame_no, encoding, w, h, len(data), webcam) assert encoding and w and h and data if not webcam: log.error("Error: webcam forwarding is not active, dropping frame") self.send_webcam_stop(device_id, "not started") return try: from xpra.codecs.pillow.decode import get_encodings assert encoding in get_encodings(), "invalid encoding specified: %s (must be one of %s)" % (encoding, get_encodings()) rgb_pixel_format = "BGRX" #BGRX from PIL import Image buf = BytesIOClass(data) img = Image.open(buf) pixels = img.tobytes('raw', rgb_pixel_format) from xpra.codecs.image_wrapper import ImageWrapper bgrx_image = ImageWrapper(0, 0, w, h, pixels, rgb_pixel_format, 32, w*4, planes=ImageWrapper.PACKED) src_format = webcam.get_src_format() if not src_format: #closed / closing return #one of those two should be present try: csc_mod = "csc_libyuv" from xpra.codecs.csc_libyuv.colorspace_converter import get_input_colorspaces, get_output_colorspaces, ColorspaceConverter #@UnresolvedImport except ImportError: self.send_webcam_stop(device_id, "no csc module") return try: assert rgb_pixel_format in get_input_colorspaces(), "unsupported RGB pixel format %s" % rgb_pixel_format assert src_format in get_output_colorspaces(rgb_pixel_format), "unsupported output colourspace format %s" % src_format except Exception as e: log.error("Error: cannot convert %s to %s using %s:", rgb_pixel_format, src_format, csc_mod) log.error(" input-colorspaces: %s", csv(get_input_colorspaces())) log.error(" output-colorspaces: %s", csv(get_output_colorspaces(rgb_pixel_format))) self.send_webcam_stop(device_id, "csc format error") return tw = webcam.get_width() th = webcam.get_height() csc = ColorspaceConverter() csc.init_context(w, h, rgb_pixel_format, tw, th, src_format) image = csc.convert_image(bgrx_image) webcam.push_image(image) #tell the client all is good: self.send_webcam_ack(device_id, frame_no) except Exception as e: log("error on %ix%i frame %i using encoding %s", w, h, frame_no, encoding, exc_info=True) log.error("Error processing webcam frame:") msg = str(e) if not msg: msg = "unknown error" log.error(" %s error" % webcam, exc_info=True) log.error(" %s", msg) self.send_webcam_stop(device_id, msg) self.stop_virtual_webcam(device_id)
def start_virtual_webcam(self, device_id, w, h): log("start_virtual_webcam%s", (device_id, w, h)) assert w > 0 and h > 0 webcam = self.webcam_forwarding_devices.get(device_id) if webcam: log.warn("Warning: virtual webcam device %s already in use,", device_id) log.warn(" stopping it first") self.stop_virtual_webcam(device_id) def fail(msg): log.error("Error: cannot start webcam forwarding") log.error(" %s", msg) self.send_webcam_stop(device_id, msg) if not self.webcam_enabled: fail("webcam forwarding is disabled") return False devices = self.get_device_options(device_id) if not devices: fail("no virtual devices found") return False if len(self.webcam_forwarding_devices) > MAX_WEBCAM_DEVICES: fail("too many virtual devices are already in use: %i" % len(self.webcam_forwarding_devices)) return False errs = {} for vid, device_info in devices.items(): log("trying device %s: %s", vid, device_info) device_str = device_info.get("device") try: from xpra.codecs.v4l2.pusher import Pusher, get_input_colorspaces #@UnresolvedImport in_cs = get_input_colorspaces() p = Pusher() src_format = in_cs[0] p.init_context(w, h, w, src_format, device_str) self.webcam_forwarding_devices[device_id] = p log.info("webcam forwarding using %s", device_str) #this tell the client to start sending, and the size to use - which may have changed: self.send_webcam_ack(device_id, 0, p.get_width(), p.get_height()) return True except Exception as e: log.error("Error: failed to start virtual webcam") log.error(" using device %s: %s", vid, device_info, exc_info=True) errs[device_str] = str(e) del e fail("all devices failed") if len(errs) > 1: log.error(" tried %i devices:", len(errs)) for device_str, err in errs.items(): log.error(" %s : %s", device_str, err) return False