diff --git a/builtin-programs/camera/usb.folk b/builtin-programs/camera/usb.folk index ac55989b..08488ae8 100644 --- a/builtin-programs/camera/usb.folk +++ b/builtin-programs/camera/usb.folk @@ -203,17 +203,25 @@ $camc code { } $camc proc cameraFrameJpeg {Camera* camera} CameraBuffer { - struct timeval timeout; - timeout.tv_sec = 1; - timeout.tv_usec = 0; - fd_set fds; - FD_ZERO(&fds); - FD_SET(camera->fd, &fds); - int r = select(camera->fd + 1, &fds, 0, 0, &timeout); - // printf("r: %d\n", r); - if (r == -1) quit("select"); + // Retry select() up to 5 times with 2 second timeout each + // Some cameras need time to start streaming + int r = 0; + for (int attempt = 0; attempt < 5 && r == 0; attempt++) { + struct timeval timeout; + timeout.tv_sec = 2; + timeout.tv_usec = 0; + fd_set fds; + FD_ZERO(&fds); + FD_SET(camera->fd, &fds); + r = select(camera->fd + 1, &fds, 0, 0, &timeout); + if (r == -1) quit("select"); + if (r == 0 && attempt < 4) { + fprintf(stderr, "camera/usb: select timeout on fd %d, retry %d/4\n", + camera->fd, attempt + 1); + } + } if (r == 0) { - FOLK_ERROR("selection failed of fd %d\n", camera->fd); + FOLK_ERROR("selection failed of fd %d after 5 attempts\n", camera->fd); } FOLK_ENSURE(camera_capture(camera) != 0); diff --git a/builtin-programs/image-lib.folk b/builtin-programs/image-lib.folk index b0920d1a..408c3d7c 100644 --- a/builtin-programs/image-lib.folk +++ b/builtin-programs/image-lib.folk @@ -369,8 +369,15 @@ $cc proc jpegDecompressGray {Jpeg jpeg int width int height int uniq} Image { int ret = tjDecompress2(handle, jpeg.start, jpeg.length, dest.data, width, 0, height, TJPF_GRAY, 0); if (ret != 0) { - tjDestroy(handle); - FOLK_ERROR("cameraDecompressGray: Decompression failed: %s\n", tjGetErrorStr()); + // Check if this is just a warning (e.g., "extraneous bytes before marker") + // or a fatal error. Warnings are common with webcam MJPEG streams. + int errCode = tjGetErrorCode(handle); + if (errCode == TJERR_FATAL) { + tjDestroy(handle); + FOLK_ERROR("cameraDecompressGray: Decompression failed: %s\n", tjGetErrorStr()); + } + // For warnings, continue with the (possibly partially corrupted) image + // fprintf(stderr, "cameraDecompressGray: Warning: %s\n", tjGetErrorStr()); } tjDestroy(handle);