fix: 不能“sender 里先按 fps 睡再去 DQBUF”
This commit is contained in:
@@ -285,6 +285,7 @@ static int open_v4l2_device(const char *device) {
|
|||||||
|
|
||||||
static int init_v4l2_device(int fd, const worker_config_t *cfg) {
|
static int init_v4l2_device(int fd, const worker_config_t *cfg) {
|
||||||
struct v4l2_format fmt;
|
struct v4l2_format fmt;
|
||||||
|
struct v4l2_streamparm parm;
|
||||||
|
|
||||||
CLEAR(fmt);
|
CLEAR(fmt);
|
||||||
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||||
@@ -297,6 +298,18 @@ static int init_v4l2_device(int fd, const worker_config_t *cfg) {
|
|||||||
perror("VIDIOC_S_FMT");
|
perror("VIDIOC_S_FMT");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CLEAR(parm);
|
||||||
|
parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||||
|
if (cfg->initial_fps > 0 && ioctl(fd, VIDIOC_G_PARM, &parm) == 0) {
|
||||||
|
if ((parm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) != 0U) {
|
||||||
|
parm.parm.capture.timeperframe.numerator = 1U;
|
||||||
|
parm.parm.capture.timeperframe.denominator = (unsigned int) cfg->initial_fps;
|
||||||
|
if (ioctl(fd, VIDIOC_S_PARM, &parm) < 0) {
|
||||||
|
perror("VIDIOC_S_PARM");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -359,6 +372,58 @@ static int queue_all_buffers(int fd, int num_buffers) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int dequeue_latest_buffer(int fd, struct v4l2_buffer *latest_buf) {
|
||||||
|
struct v4l2_buffer latest_local;
|
||||||
|
bool have_latest = false;
|
||||||
|
|
||||||
|
if (latest_buf == NULL) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
struct v4l2_buffer current;
|
||||||
|
int dq_errno;
|
||||||
|
|
||||||
|
CLEAR(current);
|
||||||
|
current.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||||
|
current.memory = V4L2_MEMORY_MMAP;
|
||||||
|
if (ioctl(fd, VIDIOC_DQBUF, ¤t) < 0) {
|
||||||
|
dq_errno = errno;
|
||||||
|
if (dq_errno == EINTR) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (dq_errno == EAGAIN) {
|
||||||
|
if (!have_latest) {
|
||||||
|
errno = EAGAIN;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
*latest_buf = latest_local;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (have_latest && ioctl(fd, VIDIOC_QBUF, &latest_local) < 0) {
|
||||||
|
perror("VIDIOC_QBUF");
|
||||||
|
}
|
||||||
|
errno = dq_errno;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (have_latest && ioctl(fd, VIDIOC_QBUF, &latest_local) < 0) {
|
||||||
|
int q_errno = errno;
|
||||||
|
|
||||||
|
perror("VIDIOC_QBUF");
|
||||||
|
if (ioctl(fd, VIDIOC_QBUF, ¤t) < 0) {
|
||||||
|
perror("VIDIOC_QBUF");
|
||||||
|
}
|
||||||
|
errno = q_errno;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
latest_local = current;
|
||||||
|
have_latest = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static AVCodecContext *create_mjpeg_decoder(const worker_config_t *cfg) {
|
static AVCodecContext *create_mjpeg_decoder(const worker_config_t *cfg) {
|
||||||
const AVCodec *decoder = avcodec_find_decoder(AV_CODEC_ID_MJPEG);
|
const AVCodec *decoder = avcodec_find_decoder(AV_CODEC_ID_MJPEG);
|
||||||
AVCodecContext *ctx;
|
AVCodecContext *ctx;
|
||||||
@@ -715,10 +780,6 @@ int main(void) {
|
|||||||
if (fps < 1) {
|
if (fps < 1) {
|
||||||
fps = 1;
|
fps = 1;
|
||||||
}
|
}
|
||||||
if (next_deadline_ms > now_ms) {
|
|
||||||
usleep((useconds_t) ((next_deadline_ms - now_ms) * 1000.0));
|
|
||||||
}
|
|
||||||
next_deadline_ms = monotonic_ms() + (1000.0 / (double) fps);
|
|
||||||
|
|
||||||
FD_ZERO(&fds);
|
FD_ZERO(&fds);
|
||||||
FD_SET(camera_fd, &fds);
|
FD_SET(camera_fd, &fds);
|
||||||
@@ -733,10 +794,7 @@ int main(void) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
CLEAR(buf);
|
if (dequeue_latest_buffer(camera_fd, &buf) != 0) {
|
||||||
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
|
||||||
buf.memory = V4L2_MEMORY_MMAP;
|
|
||||||
if (ioctl(camera_fd, VIDIOC_DQBUF, &buf) < 0) {
|
|
||||||
if (errno == EAGAIN) {
|
if (errno == EAGAIN) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -744,6 +802,13 @@ int main(void) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
now_ms = monotonic_ms();
|
||||||
|
if (now_ms < next_deadline_ms) {
|
||||||
|
drop_reason = "paced_drop";
|
||||||
|
goto requeue_and_report;
|
||||||
|
}
|
||||||
|
next_deadline_ms = now_ms + (1000.0 / (double) fps);
|
||||||
|
|
||||||
if (decode_mjpeg_frame(decoder, (uint8_t *) buffers[buf.index].start, (int) buf.bytesused, &decoded_frame) != 0) {
|
if (decode_mjpeg_frame(decoder, (uint8_t *) buffers[buf.index].start, (int) buf.bytesused, &decoded_frame) != 0) {
|
||||||
drop_reason = "decode_failed";
|
drop_reason = "decode_failed";
|
||||||
goto requeue_and_report;
|
goto requeue_and_report;
|
||||||
|
|||||||
Reference in New Issue
Block a user