I collects video using a USB camera connected to the Xavier NX. I conduct experiments on both V4L2 in C++ and pyrealsense2 in Python. The results show that in the same FPS (e.g. 60), C++ only takes about 1% CPU with lower latency, while Python takes about 20% with higher latency. And the C++ program seems do not use GPU while Python program uses GPU, whose usage increases with the FPS. Here is the main function of the C++ code.
int main() {
int fd = open("/dev/video4", O_RDWR);
if (fd == -1) {
perror("Opening camera device failed");
return 1;
}
unsigned int fps = 30;
if (set_fps(fd, fps) == 0) {
printf("FPS set to %u\n", fps);
}
struct v4l2_format format;
memset(&format, 0, sizeof(format));
format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
format.fmt.pix.width = 640;
format.fmt.pix.height = 480;
format.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
format.fmt.pix.field = V4L2_FIELD_INTERLACED;
if (ioctl(fd, VIDIOC_S_FMT, &format) == -1) {
perror("Setting camera format failed");
close(fd);
return 1;
}
struct v4l2_streamparm streamparm;
memset(&streamparm, 0, sizeof(streamparm));
streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (ioctl(fd, VIDIOC_G_PARM, &streamparm) == -1) {
perror("Getting current parameters failed");
close(fd);
return 1;
}
streamparm.parm.capture.timeperframe.numerator = 1;
streamparm.parm.capture.timeperframe.denominator = 60;
if (ioctl(fd, VIDIOC_S_PARM, &streamparm) == -1) {
perror("Setting frame rate failed");
close(fd);
return 1;
}
std::cout << "Frame rate set to: "
<< streamparm.parm.capture.timeperframe.denominator << " FPS" << std::endl;
struct v4l2_requestbuffers requestBuffers;
memset(&requestBuffers, 0, sizeof(requestBuffers));
requestBuffers.count = 1;
requestBuffers.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
requestBuffers.memory = V4L2_MEMORY_MMAP;
if (ioctl(fd, VIDIOC_REQBUFS, &requestBuffers) == -1) {
perror("Requesting buffer failed");
close(fd);
return 1;
}
struct v4l2_buffer buffer;
memset(&buffer, 0, sizeof(buffer));
buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buffer.memory = V4L2_MEMORY_MMAP;
buffer.index = 0;
if (ioctl(fd, VIDIOC_QUERYBUF, &buffer) == -1) {
perror("Querying buffer failed");
close(fd);
return 1;
}
void* bufferStart = mmap(nullptr, buffer.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buffer.m.offset);
if (bufferStart == MAP_FAILED) {
perror("mmap failed");
close(fd);
return 1;
}
int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (ioctl(fd, VIDIOC_STREAMON, &type) == -1) {
perror("Starting capture failed");
munmap(bufferStart, buffer.length);
close(fd);
return 1;
}
int frame_count = 0;
while (frame_count < 2000) {
if (ioctl(fd, VIDIOC_QBUF, &buffer) == -1) {
perror("Queueing buffer failed");
break;
}
if (ioctl(fd, VIDIOC_DQBUF, &buffer) == -1) {
perror("Dequeueing buffer failed");
break;
}
struct timeval hardware_timestamp = buffer.timestamp;
double hardware_time_sec = hardware_timestamp.tv_sec + hardware_timestamp.tv_usec / 1000000.0;
auto user_end = std::chrono::system_clock::now();
double user_time_sec = std::chrono::duration<double>(user_end.time_since_epoch()).count();
double delay_sec = user_time_sec - hardware_time_sec;
printf("Buffer Index: %u\n", buffer.index);
printf("Hardware timestamp: %.6f ms\n", hardware_time_sec);
printf("User-space timestamp: %.6f ms\n", user_time_sec);
printf("Delay: %.3f ms\n", delay_sec * 1000);
// yuyv_to_rgb(static_cast<unsigned char*>(bufferStart), rgb_buffer, 640, 480);
// save_jpeg(rgb_buffer, 640, 480, frame_count);
frame_count++;
}
ioctl(fd, VIDIOC_STREAMOFF, &type);
munmap(bufferStart, buffer.length);
close(fd);
return 0;
}
Can anyone explain the result? Is it reasonable that such differences between C++ and Python? Thank you so much!