summaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2025-02-24 17:04:16 -0500
committerpommicket <pommicket@gmail.com>2025-02-25 15:16:08 -0500
commitb164809f0ff29210344a0dbc8310d5a4916ddc70 (patch)
tree3c326c82fb9e2555ea5d7632ac0a29facba18bb1 /main.c
parent1a67ba51c7a169348e9e0be5db288d8046202a17 (diff)
fix various things, separate video & image resolution settings
Diffstat (limited to 'main.c')
-rw-r--r--main.c68
1 files changed, 46 insertions, 22 deletions
diff --git a/main.c b/main.c
index bc0dbb1..e425de0 100644
--- a/main.c
+++ b/main.c
@@ -72,7 +72,7 @@ static const char *const image_format_names[IMG_FMT_COUNT] = {"JPEG", "PNG"};
static const char *const image_format_extensions[IMG_FMT_COUNT] = {"jpg", "png"};
typedef enum {
- MODE_PICTURE,
+ MODE_IMAGE,
MODE_VIDEO,
MODE_COUNT,
@@ -82,7 +82,8 @@ typedef struct {
Hash *camera_precedence;
uint32_t pixel_format;
int timer;
- int32_t resolution[2];
+ int32_t image_resolution[2];
+ int32_t video_resolution[2];
ImageFormat image_format;
char *output_dir;
} Settings;
@@ -132,14 +133,21 @@ static void APIENTRY gl_message_callback(GLenum source, GLenum type, unsigned in
}
#endif
-static PictureFormat settings_picture_format(Settings *settings) {
+static PictureFormat settings_desired_picture_format(State *state) {
+ Settings *settings = &state->settings;
return (PictureFormat) {
- .width = settings->resolution[0],
- .height = settings->resolution[1],
+ .width = state->mode == MODE_VIDEO ? settings->video_resolution[0] : settings->image_resolution[0],
+ .height = state->mode == MODE_VIDEO ? settings->video_resolution[1] : settings->image_resolution[1],
.pixfmt = settings->pixel_format
};
}
+
+static PictureFormat settings_picture_format_for_camera(State *state, Camera *camera) {
+ PictureFormat picfmt = settings_desired_picture_format(state);
+ return camera_closest_picfmt(camera, picfmt);
+}
+
// compile a GLSL shader
GLuint gl_compile_shader(char error_buf[256], const char *code, GLenum shader_type) {
GLuint shader = gl.CreateShader(shader_type);
@@ -294,6 +302,7 @@ static void menu_select(State *state) {
state->menu_needs_rerendering = true;
// set menu_sel
PictureFormat *resolutions = camera_get_resolutions_with_pixfmt(state->camera, camera_pixel_format(state->camera));
+ state->menu_sel[MENU_RESOLUTION] = 0;
arr_foreach_ptr(resolutions, PictureFormat, resolution) {
if (resolution->width == camera_frame_width(state->camera)
&& resolution->height == camera_frame_height(state->camera)) {
@@ -314,7 +323,7 @@ static void menu_select(State *state) {
}
}
break;
- case MENU_OPT_PIXFMT: if (state->camera) {
+ case MENU_OPT_PIXFMT: if (state->camera && state->mode != MODE_VIDEO) {
state->curr_menu = MENU_PIXFMT;
state->menu_needs_rerendering = true;
// set menu_sel
@@ -346,8 +355,16 @@ static void menu_select(State *state) {
return;
}
PictureFormat *resolutions = camera_get_resolutions_with_pixfmt(state->camera, camera_pixel_format(state->camera));
+ PictureFormat resolution = resolutions[sel-1];
+ if (state->mode == MODE_VIDEO) {
+ settings->video_resolution[0] = resolution.width;
+ settings->video_resolution[1] = resolution.height;
+ } else {
+ settings->image_resolution[0] = resolution.width;
+ settings->image_resolution[1] = resolution.height;
+ }
camera_set_format(state->camera,
- resolutions[sel-1],
+ resolution,
camera_access_method(state->camera),
false);
arr_free(resolutions);
@@ -365,7 +382,8 @@ static void menu_select(State *state) {
} else {
camera_close(state->camera);
state->camera = new_camera;
- if (camera_open(state->camera, settings_picture_format(settings))) {
+ PictureFormat picfmt = settings_picture_format_for_camera(state, state->camera);
+ if (camera_open(state->camera, picfmt)) {
// put at highest precedence
move_to_highest_precedence(&state->settings, state->camera);
} else {
@@ -381,8 +399,8 @@ static void menu_select(State *state) {
state->menu_needs_rerendering = true;
return;
}
- uint32_t pixfmt = pixfmts[sel-1];
- PictureFormat new_picfmt = camera_closest_resolution(state->camera, pixfmt, settings->resolution[0], settings->resolution[1]);
+ settings->pixel_format = pixfmts[sel-1];
+ PictureFormat new_picfmt = settings_picture_format_for_camera(state, state->camera);
arr_free(pixfmts);
camera_set_format(state->camera,
new_picfmt,
@@ -432,7 +450,7 @@ static void select_camera(State *state) {
}
state->camera = state->cameras[camera_idx];
}
- if (camera_open(state->camera, settings_picture_format(settings))) {
+ if (camera_open(state->camera, settings_picture_format_for_camera(state, state->camera))) {
bool already_there = false;
arr_foreach_ptr(settings->camera_precedence, Hash, h) {
if (hash_eq(*h, camera_hash(state->camera))) {
@@ -580,7 +598,7 @@ static bool take_picture(State *state) {
snprintf(path + strlen(path), sizeof path - strlen(path), ".%s", extension);
bool success = false;
switch (state->mode) {
- case MODE_PICTURE:
+ case MODE_IMAGE:
switch (settings->image_format) {
case IMG_FMT_JPEG:
success = camera_save_jpg(state->camera, path, 90);
@@ -1016,20 +1034,26 @@ void main() {\n\
}
break;
case SDLK_TAB:
+ if (state->curr_menu) break;
if (video_is_recording(state->video)) break;
state->mode = (state->mode + 1) % MODE_COUNT;
switch (state->mode) {
- case MODE_PICTURE:
- // TODO: go back to normal settings
- break;
- case MODE_VIDEO:
- // TODO: configurable width/height
- camera_set_format(state->camera, (PictureFormat) {
- .width = 1280,
- .height = 720,
- .pixfmt = V4L2_PIX_FMT_YUV420
- }, CAMERA_ACCESS_MMAP, false);
+ case MODE_IMAGE:
+ camera_set_format(state->camera,
+ settings_picture_format_for_camera(state, state->camera),
+ camera_access_method(state->camera), false);
break;
+ case MODE_VIDEO: {
+ PictureFormat desired = settings_desired_picture_format(state);
+ desired.pixfmt = V4L2_PIX_FMT_YUV420;
+ // default to 720p for video
+ if (!desired.width) desired.width = 1280;
+ if (!desired.height) desired.height = 720;
+ PictureFormat picfmt = camera_closest_picfmt(state->camera, desired);
+ // force V4L2 to do the conversion if we have to
+ picfmt.pixfmt = V4L2_PIX_FMT_YUV420;
+ camera_set_format(state->camera, picfmt, camera_access_method(state->camera), false);
+ } break;
case MODE_COUNT:
assert(false);
break;