summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2025-02-25 10:56:04 -0500
committerpommicket <pommicket@gmail.com>2025-02-25 15:16:08 -0500
commit9b90ceee792cb51917af474ddcbc47edaacff16b (patch)
tree86c883958b05d42061a7d63c0cfbd4a607046626
parente8c5a90014982f423fbdcd3f8b3e7edacdb4b91c (diff)
fix audio issue
-rw-r--r--camera.c12
-rw-r--r--main.c1
-rw-r--r--video.c89
3 files changed, 60 insertions, 42 deletions
diff --git a/camera.c b/camera.c
index ed0510d..0a11ff2 100644
--- a/camera.c
+++ b/camera.c
@@ -321,8 +321,6 @@ static bool camera_stop_io(Camera *camera) {
camera->streaming = false;
// Just doing VIDIOC_STREAMOFF doesn't seem to be enough to prevent EBUSY.
// (Even if we dequeue all buffers afterwards)
- // Re-opening doesn't seem to be necessary for read-based access for me,
- // but idk if that's true on all cameras.
v4l2_close(camera->fd);
camera->fd = v4l2_open(camera->devnode, O_RDWR);
if (camera->fd < 0) {
@@ -751,6 +749,13 @@ void camera_close(Camera *camera) {
camera->userp_frames[i] = NULL;
}
if (camera->fd >= 0) {
+ if (camera->streaming) {
+ if (v4l2_ioctl(camera->fd, VIDIOC_STREAMOFF,
+ (enum v4l2_buf_type[1]) { V4L2_BUF_TYPE_VIDEO_CAPTURE }) != 0) {
+ perror("v4l2_ioctl VIDIOC_STREAMOFF");
+ }
+ camera->streaming = false;
+ }
v4l2_close(camera->fd);
camera->fd = -1;
}
@@ -794,6 +799,9 @@ uint64_t camera_framerates_supported(Camera *camera) {
bool camera_set_format(Camera *camera, PictureFormat picfmt, int desired_framerate, CameraAccessMethod access, bool force) {
assert(camera);
+ if (camera->fd < 0) {
+ return false;
+ }
if (!access) {
// by default, don't change access method
access = camera->access_method;
diff --git a/main.c b/main.c
index a731874..084c38c 100644
--- a/main.c
+++ b/main.c
@@ -1,6 +1,5 @@
/*
TODO
--figure out why audio is broken for low framerate videos
-save/restore settings
*/
#define _GNU_SOURCE
diff --git a/video.c b/video.c
index b3e38ee..b04136e 100644
--- a/video.c
+++ b/video.c
@@ -12,7 +12,7 @@
#include "camera.h"
// no real harm in making this bigger, other than increased memory usage.
-#define AUDIO_QUEUE_SIZE 65536
+#define AUDIO_QUEUE_SIZE ((size_t)128 << 10)
#define AUDIO_NOT_RECORDING (UINT32_MAX)
#define AUDIO_QUIT (UINT32_MAX - 1)
@@ -82,8 +82,14 @@ static int audio_thread(void *data) {
// reset tail now that we are recording
tail = 0;
}
- if (result >= 0) {
+ if ((tail - head + AUDIO_QUEUE_SIZE) % AUDIO_QUEUE_SIZE > AUDIO_QUEUE_SIZE * 3 / 4) {
+ if (warned[0] < 10) {
+ fprintf(stderr, "\x1b[93mwarning:\x1b[0m audio overrun\n");
+ warned[0]++;
+ }
+ } else if (result >= 0) {
const uint32_t nfloats = sizeof buf / sizeof(float);
+ printf("capture: %u \n",nfloats);
if (tail + nfloats <= AUDIO_QUEUE_SIZE) {
// easy case
memcpy(&ctx->audio_queue[tail], buf, sizeof buf);
@@ -290,51 +296,56 @@ bool video_submit_frame(VideoContext *ctx, Camera *camera) {
if (!ctx || !camera || !ctx->recording) return false;
double curr_time = get_time_double();
double time_since_start = curr_time - ctx->start_time;
- // process audio
- if (ctx->audio_thread_created) while (true) {
- int err = av_frame_make_writable(ctx->audio_frame);
- if (err < 0) {
- fprintf(stderr, "error: av_frame_make_writable: %s\n", av_err2str(err));
- break;
- }
- ctx->audio_frame->pts = ctx->next_audio_pts;
- uint32_t nfloats = (uint32_t)ctx->audio_frame_samples * 2;
+ if (ctx->audio_thread_created) {
+ // process audio
// only this thread writes to head, so relaxed is fine.
uint32_t head = atomic_load_explicit(&ctx->audio_head, memory_order_relaxed);
uint32_t tail = atomic_load(&ctx->audio_tail);
- bool frame_ready = false;
- if (tail == AUDIO_NOT_RECORDING) {
- // capture thread doesn't even know we're recording yet
- } else if (head + nfloats < AUDIO_QUEUE_SIZE) {
- // easy case
- frame_ready = head + nfloats <= tail;
- if (frame_ready) {
- for (uint32_t s = 0; s < nfloats; s++) {
- ((float *)ctx->audio_frame->data[s % 2])[s / 2] = ctx->audio_queue[head + s];
- }
- head += nfloats;
+ printf("start recv: head=%u tail=%u\n",head,tail);
+ while (true) {
+ int err = av_frame_make_writable(ctx->audio_frame);
+ if (err < 0) {
+ fprintf(stderr, "error: av_frame_make_writable: %s\n", av_err2str(err));
+ break;
}
- } else {
- // "wrap around" case
- frame_ready = head + nfloats - AUDIO_QUEUE_SIZE <= tail && tail <= AUDIO_QUEUE_SIZE / 2;
- if (frame_ready) {
- for (uint32_t s = 0; s < AUDIO_QUEUE_SIZE - head; s++) {
- ((float *)ctx->audio_frame->data[s % 2])[s / 2] = ctx->audio_queue[head + s];
+ ctx->audio_frame->pts = ctx->next_audio_pts;
+ uint32_t nfloats = (uint32_t)ctx->audio_frame_samples * 2;
+ bool frame_ready = false;
+ if (tail == AUDIO_NOT_RECORDING) {
+ // capture thread doesn't even know we're recording yet
+ } else if (head + nfloats < AUDIO_QUEUE_SIZE) {
+ // easy case
+ frame_ready = head + nfloats <= tail || head > tail /* tail wrapped around */;
+ if (frame_ready) {
+ for (uint32_t s = 0; s < nfloats; s++) {
+ ((float *)ctx->audio_frame->data[s % 2])[s / 2] = ctx->audio_queue[head + s];
+ }
+ head += nfloats;
}
- for (uint32_t s = 0; s < head + nfloats - AUDIO_QUEUE_SIZE; s++) {
- uint32_t i = AUDIO_QUEUE_SIZE - head + s;
- ((float *)ctx->audio_frame->data[i % 2])[i / 2] = ctx->audio_queue[s];
+ } else {
+ // "wrap around" case
+ frame_ready = head + nfloats - AUDIO_QUEUE_SIZE <= tail && tail < head;
+ if (frame_ready) {
+ for (uint32_t s = 0; s < AUDIO_QUEUE_SIZE - head; s++) {
+ ((float *)ctx->audio_frame->data[s % 2])[s / 2] = ctx->audio_queue[head + s];
+ }
+ for (uint32_t s = 0; s < head + nfloats - AUDIO_QUEUE_SIZE; s++) {
+ uint32_t i = AUDIO_QUEUE_SIZE - head + s;
+ ((float *)ctx->audio_frame->data[i % 2])[i / 2] = ctx->audio_queue[s];
+ }
+ head = head + nfloats - AUDIO_QUEUE_SIZE;
}
- head = head + nfloats - AUDIO_QUEUE_SIZE;
+ }
+ if (frame_ready) {
+ ctx->next_audio_pts += ctx->audio_frame_samples;
+ printf("recvd: %u\n",nfloats);
+ write_frame(ctx, ctx->audio_encoder, ctx->audio_stream, ctx->audio_frame);
+ } else {
+ printf("end recv\n");
+ break;
}
}
- if (frame_ready) {
- atomic_store(&ctx->audio_head, head);
- ctx->next_audio_pts += ctx->audio_frame_samples;
- write_frame(ctx, ctx->audio_encoder, ctx->audio_stream, ctx->audio_frame);
- } else {
- break;
- }
+ atomic_store(&ctx->audio_head, head);
}
// process video
int64_t video_pts = (int64_t)(time_since_start