Не могли бы вы показать, как получить и установить качество сжатия JPEG (с пиксельным форматом JPEG) в V4L2 через C ++?
Я могу определить различные форматы пикселей, поддерживаемые камерой, и соответствующие разрешения и частоты кадров. Я также могу выбрать их и соответственно захватывать изображения JPEG. Однако я не могу установить и получить качество JPEG.
Я использую Linux Mint и камеру Logitech C910.
Камера, кажется, выставляет этот параметр, так как
v4l2-ctl --all
производит
JPEG Compression Controls
compression_quality (int) : min=50 max=87 step=1 default=75 value=75
[...]
Тем не менее, код
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
#include <iostream>
using namespace std;
int main()
{
int fd = open("/dev/video0", O_RDWR);
if (fd == -1)
{
perror("open: "); return 1;
}
{
// first option
v4l2_jpegcompression ctrl={0};
if(ioctl(fd, VIDIOC_G_JPEGCOMP, &ctrl)<0)
{
perror("VIDIOC_G_JPEGCOMP:");
}
else
{
cout<<"QUALITY:"<<ctrl.quality<<endl;
}
}
{
// second option
v4l2_ext_control extCtrl={0};
extCtrl.id = V4L2_CID_JPEG_COMPRESSION_QUALITY;
extCtrl.size = 0;
extCtrl.value = 100;
v4l2_ext_controls extCtrls={0};
extCtrls.controls = &extCtrl;
extCtrls.count = 1;
extCtrls.ctrl_class = V4L2_CTRL_CLASS_JPEG;
if(ioctl(fd, VIDIOC_G_EXT_CTRLS, &extCtrls)<0)
{
perror("VIDIOC_G_EXT_CTRLS:");
}
}
{
// third option
v4l2_ext_control extCtrl={0};
extCtrl.id = V4L2_CID_JPEG_COMPRESSION_QUALITY;
extCtrl.size = 0;
extCtrl.value = 100;
v4l2_ext_controls extCtrls={0};
extCtrls.controls = &extCtrl;
extCtrls.count = 1;
extCtrls.ctrl_class = V4L2_CID_JPEG_CLASS;
if(ioctl(fd, VIDIOC_G_EXT_CTRLS, &extCtrls)<0)
{
perror("VIDIOC_G_EXT_CTRLS V4L2_CID_JPEG_CLASS:");
}
}
close(fd);
return 0;
}
который может быть скомпилирован через
g++ query.cpp -o query.out
производит:
VIDIOC_G_JPEGCOMP:: Inappropriate ioctl for device
VIDIOC_G_EXT_CTRLS:: Invalid argument
VIDIOC_G_EXT_CTRLS V4L2_CID_JPEG_CLASS:: Invalid argument
void check_controls(int fd) {
struct v4l2_queryctrl qctrl;
memset(&qctrl, 0, sizeof(qctrl));
qctrl.id = V4L2_CTRL_FLAG_NEXT_CTRL;
while (0 == ioctl (fd, VIDIOC_QUERYCTRL, &qctrl)) {
printf("ID = %08x\n", qctrl.id);
/* ... */
qctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
}
}
Это выведет в шестнадцатеричном виде список сопоставленных элементов управления, как в v4l2-controls.h
V4L2_CID_JPEG_COMPRESSION_QUALITY не отображается
Вы можете отобразить это в
https://www.kernel.org/doc/html/latest/media/v4l-drivers/uvcvideo.html
29.1.5. Ссылка на IOCTL
29.1.5.1. UVCIOC_CTRL_MAP — сопоставить элемент управления UVC с элементом управления V4L2
Вы можете проверить, какие параметры поддерживает камера, используя lsusb -v.
Ioctl VIDIOC_G_JPEGCOMP или VIDIOC_G_JPEGCOMP не отображается в драйвере v4l2. Я думаю, что они не используются, так как камеры их не поддерживают. Большинство камер транслируют MJPEG, автоматически контролируя качество, чтобы обеспечить целевой битрейт. Кажется, они не поддерживают изменение QP или битрейта в MJPEG. Я думаю, что идея заключается в том, что камера выдает высокий битрейт, а затем использует ffmpeg для перекодирования, например, в H264.