You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于V4L2的C++语言YUYV格式图像捕获问题求助

Troubleshooting YUYV Capture Failures with V4L2 on BeagleBone

I've dug into your code and the error you're seeing (libv4l2: error dequeuing buf: Resource temporarily unavailable), and there are a few key issues that are causing your YUYV capture to fail. Let's break down the problems and fix them step by step:

Core Issues Identified

  1. Broken select Loop Logic: You're using an assignment (errno = EINTR) instead of a comparison (errno == EINTR) in your retry condition, which breaks error handling.
  2. Unrecycled Buffers: After dequeuing a buffer, you don't requeue it back to the capture pipeline, which quickly exhausts available buffers.
  3. Unverified Format Configuration: You assume your 1920x1080 YUYV request is accepted, but the camera might be silently adjusting parameters (or failing entirely).
  4. Incorrect Image Saving: You're writing raw YUYV data directly to a PPM file (which expects RGB), but this isn't the immediate cause of your runtime error.

Step-by-Step Fixes

1. Fix the select Loop Error

This is the most critical fix—your current loop corrupts errno and fails to handle non-interrupt errors correctly. Replace your select loop with this:

do {
    FD_ZERO(&fds);
    FD_SET(fd, &fds);
    tv.tv_sec = 2;
    tv.tv_usec = 0;

    r = select(fd + 1, &fds, NULL, NULL, &tv);
} while (r == -1 && errno == EINTR); // Use comparison, not assignment

2. Requeue Buffers After Dequeuing

Every time you pull a buffer from the pipeline with VIDIOC_DQBUF, you must send it back with VIDIOC_QBUF to keep the capture process running. Here's how to update your capture logic:

// Capture first frame
do {
    FD_ZERO(&fds);
    FD_SET(fd, &fds);
    tv.tv_sec = 2;
    tv.tv_usec = 0;

    r = select(fd + 1, &fds, NULL, NULL, &tv);
} while (r == -1 && errno == EINTR);

if (r == -1) {
    perror("select");
    exit(EXIT_FAILURE);
}

clear_memmory(&(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
xioctl(fd, VIDIOC_DQBUF, &buf);
printf("Buff index: %i\n", buf.index);

// Save YUYV data (raw format, not PPM)
sprintf(out_name, "image%03d.yuv", pic_count);
fout = fopen(out_name, "w");
if (!fout) {
    perror("Cannot open image");
    exit(EXIT_FAILURE);
}
fwrite(buffers[buf.index].start, buf.bytesused, 1, fout);
fclose(fout);
pic_count++;

// Requeue the buffer for future captures
xioctl(fd, VIDIOC_QBUF, &buf);

// Repeat for second frame (with same select and requeue steps)
do {
    FD_ZERO(&fds);
    FD_SET(fd, &fds);
    tv.tv_sec = 2;
    tv.tv_usec = 0;

    r = select(fd + 1, &fds, NULL, NULL, &tv);
} while (r == -1 && errno == EINTR);

if (r == -1) {
    perror("select");
    exit(EXIT_FAILURE);
}

clear_memmory(&(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
xioctl(fd, VIDIOC_DQBUF, &buf);
printf("Buff index: %i\n", buf.index);

sprintf(out_name, "image%03d.yuv", pic_count);
fout = fopen(out_name, "w");
if (!fout) {
    perror("Cannot open image");
    exit(EXIT_FAILURE);
}
fwrite(buffers[buf.index].start, buf.bytesused, 1, fout);
fclose(fout);
pic_count++;

xioctl(fd, VIDIOC_QBUF, &buf);

3. Verify Format Configuration

After setting the format, print the actual parameters returned by the camera to confirm it accepted your YUYV request:

xioctl(fd, VIDIOC_S_FMT, &format);
printf("Device initialized with actual params:\n");
printf("Width: %d, Height: %d\n", format.fmt.pix.width, format.fmt.pix.height);
printf("Pixel format: %s (0x%x)\n", 
       format.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV ? "YUYV" : "Unknown",
       format.fmt.pix.pixelformat);
printf("Expected buffer size: %d bytes\n", format.fmt.pix.sizeimage);

If the returned format doesn't match your request, check supported resolutions with:

v4l2-ctl --list-framesizes=YUYV
v4l2-ctl --list-formats-ext

4. Convert YUYV to RGB for PPM (Optional)

To view your captured images, you'll need to convert YUYV to RGB24 before saving to PPM. Add this conversion function:

void yuyv_to_rgb24(const unsigned char* yuyv, unsigned char* rgb, int width, int height) {
    int i, j;
    for (i = 0; i < height; i++) {
        for (j = 0; j < width; j += 2) {
            unsigned char y0 = yuyv[(i * width + j) * 2];
            unsigned char u = yuyv[(i * width + j) * 2 + 1];
            unsigned char y1 = yuyv[(i * width + j + 1) * 2];
            unsigned char v = yuyv[(i * width + j + 1) * 2 + 1];

            // YUV to RGB conversion formula
            int r0 = y0 + 1.370705 * (v - 128);
            int g0 = y0 - 0.698001 * (v - 128) - 0.337633 * (u - 128);
            int b0 = y0 + 1.732446 * (u - 128);

            int r1 = y1 + 1.370705 * (v - 128);
            int g1 = y1 - 0.698001 * (v - 128) - 0.337633 * (u - 128);
            int b1 = y1 + 1.732446 * (u - 128);

            // Clamp values to 0-255
            rgb[(i * width + j) * 3] = (r0 < 0 ? 0 : (r0 > 255 ? 255 : r0));
            rgb[(i * width + j) * 3 + 1] = (g0 < 0 ? 0 : (g0 > 255 ? 255 : g0));
            rgb[(i * width + j) * 3 + 2] = (b0 < 0 ? 0 : (b0 > 255 ? 255 : b0));

            rgb[(i * width + j + 1) * 3] = (r1 < 0 ? 0 : (r1 > 255 ? 255 : r1));
            rgb[(i * width + j + 1) * 3 + 1] = (g1 < 0 ? 0 : (g1 > 255 ? 255 : g1));
            rgb[(i * width + j + 1) * 3 + 2] = (b1 < 0 ? 0 : (b1 > 255 ? 255 : b1));
        }
    }
}

Then use it when saving:

unsigned char* rgb_data = (unsigned char*)malloc(width * height * 3);
yuyv_to_rgb24((unsigned char*)buffers[buf.index].start, rgb_data, width, height);

sprintf(out_name, "image%03d.ppm", pic_count);
fout = fopen(out_name, "w");
if (!fout) {
    perror("Cannot open image");
    exit(EXIT_FAILURE);
}
fprintf(fout, "P6\n%d %d 255\n", width, height);
fwrite(rgb_data, width * height * 3, 1, fout);
fclose(fout);
free(rgb_data);

Final Notes

The buffer recycling and select loop fixes should resolve your immediate "resource unavailable" error. If you still have issues, confirm your camera supports the exact resolution/format combination you're requesting using the v4l2-ctl commands above.

内容的提问来源于stack exchange,提问作者mcf1lmnfs

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 13:13:12