mirror of https://github.com/billw2/pikrellcam.git
Zooming, preview stall warnings, HQ still resolutions.
V 4.3.2 Zoom in to a percent of the camera sensor. Selected zooms are saved as part of a Preset Settings. A large zoom can help with camera focusing. Show stall warning on preview when GPU jpeg encoder does not keep up converting the preview images and frames are dropped. This problem showed up with the HQ camera on Pi 4 where video_fps needs to lowered to around 20 to avoid stalls. I don't see the problem on Pi 2 with HQ camera or with V1 or v2 cameras, so maybe a later firmware version will help. Put in HQ still resolutions and now still resolution options shown depend on camera resolution detected. Checking archive diskfree failed to remove stills. Changed how to track through the preview jpeg encoder which preview frame to use for thumbs. Added greyworld
This commit is contained in:
parent
08ed7926e5
commit
994384dae9
BIN
pikrellcam
BIN
pikrellcam
Binary file not shown.
|
@ -1,6 +1,6 @@
|
|||
/* PiKrellCam
|
||||
|
|
||||
| Copyright (C) 2015-2019 Bill Wilson billw@gkrellm.net
|
||||
| Copyright (C) 2015-2020 Bill Wilson billw@gkrellm.net
|
||||
|
|
||||
| PiKrellCam is free software: you can redistribute it and/or modify it
|
||||
| under the terms of the GNU General Public License as published by
|
||||
|
|
44
src/config.c
44
src/config.c
|
@ -1,6 +1,6 @@
|
|||
/* PiKrellCam
|
||||
|
|
||||
| Copyright (C) 2015-2019 Bill Wilson billw@gkrellm.net
|
||||
| Copyright (C) 2015-2020 Bill Wilson billw@gkrellm.net
|
||||
|
|
||||
| PiKrellCam is free software: you can redistribute it and/or modify it
|
||||
| under the terms of the GNU General Public License as published by
|
||||
|
@ -125,7 +125,8 @@ ParameterTable awb_mode_table[] =
|
|||
{ MMAL_PARAM_AWBMODE_FLUORESCENT, "flourescent" },
|
||||
{ MMAL_PARAM_AWBMODE_INCANDESCENT, "incandescent" },
|
||||
{ MMAL_PARAM_AWBMODE_FLASH, "flash" },
|
||||
{ MMAL_PARAM_AWBMODE_HORIZON, "horizon" }
|
||||
{ MMAL_PARAM_AWBMODE_HORIZON, "horizon" },
|
||||
{ MMAL_PARAM_AWBMODE_GREYWORLD, "greyworld" }
|
||||
};
|
||||
|
||||
#define AWB_MODE_TABLE_SIZE \
|
||||
|
@ -214,6 +215,9 @@ ParameterTable parameter_table[] =
|
|||
|
||||
{ MMAL_PARAMETER_VIDEO_STABILISATION, "video_stabilisation" }, /* bool */
|
||||
{ MMAL_PARAMETER_ENABLE_RAW_CAPTURE, "raw_capture" }, /* bool */
|
||||
#if 0
|
||||
{ MMAL_PARAMETER_DRAW_BOX_FACES_AND_FOCUS, "draw_focus_box" }, /* bool */
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
@ -358,6 +362,8 @@ flip_control_set(char *option, char *setting)
|
|||
return status;
|
||||
}
|
||||
|
||||
static boolean force_crop;
|
||||
|
||||
MMAL_STATUS_T
|
||||
crop_control_set(char *option, char *setting)
|
||||
{
|
||||
|
@ -368,9 +374,31 @@ crop_control_set(char *option, char *setting)
|
|||
if (sscanf(setting, "%d %d %d %d", &crop.rect.x, &crop.rect.y,
|
||||
&crop.rect.width, &crop.rect.height) == 4)
|
||||
status = mmal_port_parameter_set(camera.control_port, &crop.hdr);
|
||||
if (option)
|
||||
force_crop = TRUE; /* crop command from FIFO, so force restoring */
|
||||
/* zoom_percent from preset changes */
|
||||
return status;
|
||||
}
|
||||
|
||||
void
|
||||
zoom_percent(int percent)
|
||||
{
|
||||
int origin, width;
|
||||
char buf[128];
|
||||
|
||||
if ( percent < 10 || percent > 100
|
||||
|| (percent == pikrellcam.zoom_percent_prev && !force_crop)
|
||||
)
|
||||
return;
|
||||
force_crop = FALSE;
|
||||
width = 65536 * percent / 100;
|
||||
origin = 65536 / 2 - width / 2;
|
||||
snprintf(buf, sizeof(buf), "%d %d %d %d", origin, origin, width, width);
|
||||
pikrellcam.zoom_motion_holdoff = 5;
|
||||
crop_control_set(NULL, buf);
|
||||
pikrellcam.zoom_percent_prev = percent;
|
||||
}
|
||||
|
||||
MMAL_STATUS_T
|
||||
color_effect_set(char *option, char *setting)
|
||||
{
|
||||
|
@ -404,6 +432,7 @@ static CameraParameter camera_parameters[] =
|
|||
|
||||
{ "video_stabilisation", "false", boolean_control_set, &pikrellcam.video_stabilisation },
|
||||
{ "raw_capture", "false", boolean_control_set, &pikrellcam.raw_capture },
|
||||
// { "draw_focus_box", "false", boolean_control_set, &pikrellcam.draw_focus_box },
|
||||
|
||||
{ "rotation", "0", rotation_control_set, &pikrellcam.rotation },
|
||||
{ "exposure_mode", "auto", exposure_mode_set, &pikrellcam.exposure_mode },
|
||||
|
@ -750,6 +779,10 @@ static Config config[] =
|
|||
"#",
|
||||
"motion_show_counts", "off", FALSE, {.value = &pikrellcam.motion_show_counts}, config_value_bool_set },
|
||||
|
||||
{ "# If on, show a warning if the preview mjpeg encoder stalls.\n"
|
||||
"#",
|
||||
"preview_stall_warning", "on", FALSE, {.value = &pikrellcam.preview_stall_warning}, config_value_bool_set },
|
||||
|
||||
{ "# Minimum width and height in pixels for the substitution width and height\n"
|
||||
"# variables for motion detect areas in the preview jpeg.\n"
|
||||
"# This minimum helps with possible frame skew for smaller relatively\n"
|
||||
|
@ -1158,7 +1191,7 @@ static Config config[] =
|
|||
{ "# Annotate text background color. Set to \"none\" for no background.\n"
|
||||
"# Otherwise, set to a hex rgb value, eg \"000000\" for black or \"808080\" for gray.\n"
|
||||
"#",
|
||||
"annotate_text_background_color", "none", FALSE, {.string = &pikrellcam.annotate_text_background_color }, config_string_set },
|
||||
"annotate_text_background_color", "808080", FALSE, {.string = &pikrellcam.annotate_text_background_color }, config_string_set },
|
||||
|
||||
{ "# Annotate text brightness. Range: integer from 0 - 255\n"
|
||||
"# Text cannot be set to a color, only to a brightness..\n"
|
||||
|
@ -1279,7 +1312,7 @@ config_load(char *config_file)
|
|||
if ((f = fopen(config_file, "r")) == NULL)
|
||||
return FALSE;
|
||||
|
||||
pikrellcam.config_sequence_new = 45;
|
||||
pikrellcam.config_sequence_new = 47;
|
||||
|
||||
while (fgets(linebuf, sizeof(linebuf), f))
|
||||
{
|
||||
|
@ -1317,6 +1350,9 @@ config_load(char *config_file)
|
|||
)
|
||||
pikrellcam.motion_record_time_limit = 10;
|
||||
|
||||
pikrellcam.zoom_percent = 100;
|
||||
pikrellcam.zoom_percent_prev = 100;
|
||||
|
||||
if (pikrellcam.motion_stills_per_minute > 60)
|
||||
pikrellcam.motion_stills_per_minute = 60;
|
||||
else if (pikrellcam.motion_stills_per_minute < 1)
|
||||
|
|
141
src/display.c
141
src/display.c
|
@ -1,6 +1,6 @@
|
|||
/* PiKrellCam
|
||||
|
|
||||
| Copyright (C) 2015-2019 Bill Wilson billw@gkrellm.net
|
||||
| Copyright (C) 2015-2020 Bill Wilson billw@gkrellm.net
|
||||
|
|
||||
| PiKrellCam is free software: you can redistribute it and/or modify it
|
||||
| under the terms of the GNU General Public License as published by
|
||||
|
@ -502,9 +502,10 @@ display_preset_settings(void)
|
|||
JUSTIFY_LEFT, "Setup->Preset->New");
|
||||
}
|
||||
|
||||
snprintf(info1, sizeof(info1), "Mag %d Cnt %d Burst %d,%d",
|
||||
snprintf(info1, sizeof(info1), "Mag %d Cnt %d Burst %d,%d Zoom %d%%",
|
||||
(int) sqrt(mf->mag2_limit), mf->mag2_limit_count,
|
||||
pikrellcam.motion_burst_count, pikrellcam.motion_burst_frames);
|
||||
pikrellcam.motion_burst_count, pikrellcam.motion_burst_frames,
|
||||
pikrellcam.zoom_percent);
|
||||
i420_print(&bottom_status_area, normal_font, 0xff,
|
||||
pikrellcam.have_servos ? 1 : 2,
|
||||
-6 * normal_font->char_width, 0,
|
||||
|
@ -608,10 +609,11 @@ motion_draw(uint8_t *i420)
|
|||
MotionRegion *mreg;
|
||||
CompositeVector *vec;
|
||||
SList *mrlist;
|
||||
char *msg, *fifo_msg, info[100], status[100];
|
||||
char *msg, *stall_msg, *fifo_msg, buf[32], info[200], status[100];
|
||||
int16_t color; /* just B&W */
|
||||
int i, x, y, dx, dy, r, r_unit;
|
||||
int t_record, t_hold;
|
||||
static int stall_warning;
|
||||
|
||||
if (!glcd)
|
||||
return;
|
||||
|
@ -629,6 +631,17 @@ motion_draw(uint8_t *i420)
|
|||
}
|
||||
|
||||
fifo_msg = "";
|
||||
|
||||
if (pikrellcam.mjpeg_stall_count > 0)
|
||||
stall_warning = 6;
|
||||
if (stall_warning > 0)
|
||||
{
|
||||
--stall_warning;
|
||||
stall_msg = " Preview stall! See Preview_Stall_Warning in Help";
|
||||
}
|
||||
else
|
||||
stall_msg = "";
|
||||
|
||||
if (!inform_shown && (mf->show_preset || pikrellcam.preset_notify))
|
||||
{
|
||||
for (mrlist = mf->motion_region_list; mrlist; mrlist = mrlist->next)
|
||||
|
@ -714,8 +727,8 @@ motion_draw(uint8_t *i420)
|
|||
|
||||
if (mf->frame_window > 0 && mf->motion_status == MOTION_NONE)
|
||||
{
|
||||
snprintf(status, sizeof(status), "confirming[%d]", mf->frame_window);
|
||||
msg = status;
|
||||
snprintf(buf, sizeof(buf), "confirming[%d]", mf->frame_window);
|
||||
msg = buf;
|
||||
}
|
||||
else if (mf->motion_status & MOTION_DETECTED)
|
||||
{
|
||||
|
@ -732,10 +745,12 @@ motion_draw(uint8_t *i420)
|
|||
msg = "noise";
|
||||
else
|
||||
msg = "quiet";
|
||||
|
||||
if (mf->frame_vector.mag2_count > 0)
|
||||
snprintf(status, sizeof(status), "%s:%-3d", msg, mf->frame_vector.mag2_count);
|
||||
snprintf(status, sizeof(status), "%s:%-3d%s",
|
||||
msg, mf->frame_vector.mag2_count, stall_msg);
|
||||
else
|
||||
snprintf(status, sizeof(status), "%s", msg);
|
||||
snprintf(status, sizeof(status), "%s%s", msg, stall_msg);
|
||||
|
||||
if (pikrellcam.motion_show_counts)
|
||||
{
|
||||
|
@ -756,7 +771,12 @@ motion_draw(uint8_t *i420)
|
|||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mf->selected_region = -1;
|
||||
if (pikrellcam.preview_stall_warning)
|
||||
i420_print(&bottom_status_area, normal_font, 0xff, 0, 0, 0,
|
||||
JUSTIFY_LEFT, stall_msg);
|
||||
}
|
||||
|
||||
t_record = vcb->record_elapsed_time;
|
||||
|
||||
|
@ -930,7 +950,8 @@ static SList *menu_video_presets_list;
|
|||
static int menu_video_presets_index;
|
||||
|
||||
static SList *menu_still_presets_list;
|
||||
static int menu_still_presets_index;
|
||||
static int menu_still_presets_index,
|
||||
menu_still_presets_list_size;
|
||||
|
||||
static SList *menu_picture_list;
|
||||
static int menu_picture_index;
|
||||
|
@ -973,6 +994,7 @@ static char *video_presets_entry[] =
|
|||
"1640x1232", // V2 4:3
|
||||
"1640x922", // V2 16:9
|
||||
"1296x972", // V1 4:3
|
||||
"1012x760", // HQ 4:3
|
||||
"1024x768",
|
||||
"1024x576"
|
||||
};
|
||||
|
@ -984,12 +1006,15 @@ static char *still_presets_entry[] =
|
|||
{
|
||||
"1920x1080",
|
||||
"1280x720",
|
||||
"3280x2464", // v2
|
||||
"2592x1944",
|
||||
"2592x1458",
|
||||
"1920x1440",
|
||||
"1640x1232", // V2 4:3
|
||||
"1640x922", // V2 16:9
|
||||
"4056x3040", // HQ 4:3
|
||||
"4056x2280", // HQ 16:9
|
||||
"3280x2464", // v2 4:3
|
||||
"3280x1545", // v2 16:9
|
||||
"2592x1944", // v1 4:3
|
||||
"2592x1458", // v1 16:9
|
||||
"1920x1440", // all 4:3
|
||||
"1640x1232", // all 4:3
|
||||
"1640x922", // all 16:9
|
||||
"1296x972",
|
||||
"1024x768",
|
||||
"1024x576"
|
||||
|
@ -1040,7 +1065,8 @@ static char *white_balance_entry[] =
|
|||
"flourescent",
|
||||
"incandescent",
|
||||
"flash",
|
||||
"horizon"
|
||||
"horizon",
|
||||
"greyworld"
|
||||
};
|
||||
|
||||
#define N_WHITE_BALANCE_ENTRIES \
|
||||
|
@ -1104,6 +1130,7 @@ static Adjustment picture_adjustment[] =
|
|||
{ "iso", 0, 800, 100, 0, 0, 0, 0, "", NULL, NULL },
|
||||
{ "exposure_compensation", -25, 25, 1, 0, 0, 0, 0, "", NULL, NULL },
|
||||
{ "video_stabilisation", 0, 1, 1, 0, 0, 0, 0, "", NULL, NULL },
|
||||
// { "draw_focus_box", 0, 1, 1, 0, 0, 0, 0, "", NULL, NULL },
|
||||
{ "rotation", 0, 270, 90, 0, 0, 0, 0, "", NULL, NULL },
|
||||
{ "hflip", 0, 1, 1, 0, 0, 0, 0, "", NULL, NULL },
|
||||
{ "vflip", 0, 1, 1, 0, 0, 0, 0, "", NULL, NULL },
|
||||
|
@ -1137,13 +1164,17 @@ Adjustment motion_limit_adjustment[] =
|
|||
{ "Vector_Magnitude", 2, 50, 1, 0, 0, 0, 0, "", NULL, &pikrellcam.motion_magnitude_limit },
|
||||
{ "Vector_Count", 2, 50, 1, 0, 0, 0, 0, "", NULL, &pikrellcam.motion_magnitude_limit_count },
|
||||
{ "Burst_Count", 50, 2000, 10, 0, 0, 0, 0, "", NULL, &pikrellcam.motion_burst_count },
|
||||
{ "Burst_Frames", 2, 20, 1, 0, 0, 0, 0, "", NULL, &pikrellcam.motion_burst_frames }
|
||||
{ "Burst_Frames", 2, 20, 1, 0, 0, 0, 0, "", NULL, &pikrellcam.motion_burst_frames },
|
||||
{ "Zoom_Percent", 10, 100, 2, 0, 0, 0, 0, "", NULL, &pikrellcam.zoom_percent }
|
||||
};
|
||||
|
||||
#define ZOOM_REGION_INDEX 4
|
||||
|
||||
#define N_MOTION_LIMIT_ADJUSTMENTS \
|
||||
(sizeof(motion_limit_adjustment) / sizeof(Adjustment))
|
||||
|
||||
|
||||
|
||||
/* Some settings djustment changes are made to a temp struct to avoid thrashing
|
||||
| camera destroys/creates. Final change is applied if/when SEL is clicked.
|
||||
*/
|
||||
|
@ -1161,6 +1192,7 @@ Adjustment settings_adjustment[] =
|
|||
{ "Vector_Counts", 0, 1, 1, 0, 0, 0, 0, "", NULL, &pikrellcam.motion_show_counts },
|
||||
{ "Vector_Dimming", 30, 60, 1, 0, 0, 0, 0, "", NULL, &pikrellcam.motion_vectors_dimming },
|
||||
{ "Preview_Clean", 0, 1, 1, 0, 0, 0, 0, "", NULL, &pikrellcam.motion_preview_clean },
|
||||
{ "Preview_Stall_Warning", 0, 1, 1, 0, 0, 0, 0, "", NULL, &pikrellcam.preview_stall_warning },
|
||||
};
|
||||
|
||||
|
||||
|
@ -1230,6 +1262,17 @@ adjustment_is_servo_limits(void)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static boolean
|
||||
adjustment_is_zoom(void)
|
||||
{
|
||||
if ( display_state == DISPLAY_ADJUSTMENT
|
||||
&& adjustments == &motion_limit_adjustment[0]
|
||||
&& *display_menu_index == ZOOM_REGION_INDEX
|
||||
)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static boolean
|
||||
adjustment_is_servo_pan_limits(void)
|
||||
{
|
||||
|
@ -1315,6 +1358,7 @@ apply_adjustment(void)
|
|||
settings->mag_limit_count = pikrellcam.motion_magnitude_limit_count;
|
||||
settings->burst_count = pikrellcam.motion_burst_count;
|
||||
settings->burst_frames = pikrellcam.motion_burst_frames;
|
||||
settings->zoom_percent = pikrellcam.zoom_percent;
|
||||
pikrellcam.preset_modified = TRUE;
|
||||
}
|
||||
else
|
||||
|
@ -1368,7 +1412,9 @@ revert_adjustment(void)
|
|||
else
|
||||
*(cur_adj->config_value) = cur_adj->revert_value;
|
||||
}
|
||||
if (adjustment_is_servo_limits())
|
||||
if (adjustment_is_zoom())
|
||||
zoom_percent(pikrellcam.zoom_percent);
|
||||
else if (adjustment_is_servo_limits())
|
||||
servo_move(pan_save, tilt_save, pikrellcam.servo_move_step_msec);
|
||||
}
|
||||
|
||||
|
@ -1533,7 +1579,9 @@ display_adjustment(uint8_t *i420)
|
|||
else
|
||||
*(cur_adj->config_value) = cur_adj->value;
|
||||
|
||||
if (adjustment_is_servo_pan_limits())
|
||||
if (adjustment_is_zoom())
|
||||
zoom_percent(pikrellcam.zoom_percent);
|
||||
else if (adjustment_is_servo_pan_limits())
|
||||
{
|
||||
preset_pan_range(&max, &min);
|
||||
if (cur_adj->value <= min || cur_adj->value >= max)
|
||||
|
@ -1625,6 +1673,19 @@ display_adjustment(uint8_t *i420)
|
|||
i420_print(da, font, 0xff, 2, 0, 0, JUSTIFY_CENTER, cur_adj->name);
|
||||
}
|
||||
|
||||
void
|
||||
display_motion_limit_adjustment_sync(PresetSettings *settings)
|
||||
{
|
||||
if ( display_state != DISPLAY_ADJUSTMENT
|
||||
|| adjustments != &motion_limit_adjustment[0]
|
||||
|| !cur_adj
|
||||
)
|
||||
return;
|
||||
|
||||
cur_adj_start = TRUE;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
display_draw_menu(uint8_t *i420)
|
||||
{
|
||||
|
@ -1904,8 +1965,13 @@ display_command(char *cmd)
|
|||
{
|
||||
if (!strcmp(video_presets_entry[i], "720p"))
|
||||
{
|
||||
width = 1296;
|
||||
height = 730;
|
||||
width = 1280;
|
||||
height = 720;
|
||||
}
|
||||
else if (!strcmp(video_presets_entry[i], "1080p"))
|
||||
{
|
||||
width = 1920;
|
||||
height = 1080;
|
||||
}
|
||||
else
|
||||
sscanf(video_presets_entry[i], "%dx%d", &width, &height);
|
||||
|
@ -1921,15 +1987,19 @@ display_command(char *cmd)
|
|||
display_menu_index = &menu_still_presets_index;
|
||||
display_state = DISPLAY_MENU;
|
||||
display_menu = STILL_PRESET;
|
||||
for (i = N_STILL_PRESET_ENTRIES - 1; i > 0 ; --i)
|
||||
for (i = 0, list = display_menu_list; list; ++i, list = list->next)
|
||||
{
|
||||
sscanf(still_presets_entry[i], "%dx%d", &width, &height);
|
||||
entry = (MenuEntry *) list->data;
|
||||
sscanf(entry->name, "%dx%d", &width, &height);
|
||||
if ( pikrellcam.camera_config.still_width == width
|
||||
&& pikrellcam.camera_config.still_height == height
|
||||
)
|
||||
break;
|
||||
}
|
||||
menu_still_presets_index = i;
|
||||
if (i < menu_still_presets_list_size)
|
||||
menu_still_presets_index = i;
|
||||
else
|
||||
menu_still_presets_index = 0;
|
||||
break;
|
||||
|
||||
case METERING:
|
||||
|
@ -2145,7 +2215,7 @@ display_init(void)
|
|||
DrawArea da;
|
||||
MenuEntry *entry;
|
||||
Adjustment *adj;
|
||||
int i, position;
|
||||
int i, position, width, height;
|
||||
|
||||
if (!glcd)
|
||||
glcd = glcd_i420_init();
|
||||
|
@ -2278,14 +2348,23 @@ display_init(void)
|
|||
}
|
||||
if (!menu_still_presets_list)
|
||||
{
|
||||
menu_still_presets_list_size = 0;
|
||||
for (i = 0, position = 0; i < N_STILL_PRESET_ENTRIES; ++i)
|
||||
{
|
||||
entry = calloc(1, sizeof(MenuEntry));
|
||||
entry->name = still_presets_entry[i];
|
||||
entry->length = strlen(entry->name);
|
||||
entry->line_position = position;
|
||||
position += entry->length + 1;
|
||||
menu_still_presets_list = slist_append(menu_still_presets_list, entry);
|
||||
sscanf(still_presets_entry[i], "%dx%d", &width, &height);
|
||||
if ( pikrellcam.camera_width_max >= width
|
||||
&& pikrellcam.camera_height_max >= height
|
||||
)
|
||||
{
|
||||
entry = calloc(1, sizeof(MenuEntry));
|
||||
entry->name = still_presets_entry[i];
|
||||
entry->length = strlen(entry->name);
|
||||
entry->line_position = position;
|
||||
position += entry->length + 1;
|
||||
++menu_still_presets_list_size;
|
||||
menu_still_presets_list =
|
||||
slist_append(menu_still_presets_list, entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!menu_picture_list)
|
||||
|
|
40
src/event.c
40
src/event.c
|
@ -1,6 +1,6 @@
|
|||
/* PiKrellCam
|
||||
|
|
||||
| Copyright (C) 2015-2019 Bill Wilson billw@gkrellm.net
|
||||
| Copyright (C) 2015-2020 Bill Wilson billw@gkrellm.net
|
||||
|
|
||||
| PiKrellCam is free software: you can redistribute it and/or modify it
|
||||
| under the terms of the GNU General Public License as published by
|
||||
|
@ -490,7 +490,7 @@ static boolean
|
|||
video_diskfree_percent_delete(char *media_dir, boolean *empty)
|
||||
{
|
||||
struct dirent **mp4_list = NULL;
|
||||
char *s, video_dir[256], thumb_dir[256], fname[256];
|
||||
char *s, video_dir[256], thumb_dir[256], fname[512];
|
||||
int i, n, low_space;
|
||||
boolean done = FALSE;
|
||||
|
||||
|
@ -552,7 +552,7 @@ static boolean
|
|||
still_diskfree_percent_delete(char *media_dir, char *sub_dir, boolean *empty)
|
||||
{
|
||||
struct dirent **jpg_list = NULL;
|
||||
char still_dir[256], fname[256];
|
||||
char *s, still_dir[256], fname[600], thumb_base[300];
|
||||
int i, n, low_space;
|
||||
boolean done = FALSE;
|
||||
|
||||
|
@ -577,6 +577,15 @@ still_diskfree_percent_delete(char *media_dir, char *sub_dir, boolean *empty)
|
|||
snprintf(fname, sizeof(fname), "%s/%s",
|
||||
still_dir, jpg_list[i]->d_name);
|
||||
unlink(fname);
|
||||
|
||||
snprintf(thumb_base, sizeof(thumb_base), "%s", jpg_list[i]->d_name);
|
||||
if ((s = strstr(thumb_base, ".jpg")) != NULL)
|
||||
{
|
||||
*s = '\0';
|
||||
snprintf(fname, sizeof(fname), "%s/.thumbs/%s.th.jpg",
|
||||
still_dir, thumb_base);
|
||||
unlink(fname);
|
||||
}
|
||||
log_printf("Low disk space, deleted: %s\n", fname);
|
||||
|
||||
if (empty && i == n - 1)
|
||||
|
@ -605,7 +614,7 @@ event_archive_diskfree_percent(char *type)
|
|||
**month_list = NULL,
|
||||
**day_list = NULL;;
|
||||
int y, n_yr, m, n_mon, d, n_day;
|
||||
char year_dir[256], mon_dir[256], day_dir[256], del_dir[256];
|
||||
char year_dir[300], mon_dir[600], day_dir[800], del_dir[1000];
|
||||
boolean done = FALSE, dir_empty;
|
||||
|
||||
if (!diskfree_is_low(pikrellcam.archive_dir))
|
||||
|
@ -645,11 +654,32 @@ event_archive_diskfree_percent(char *type)
|
|||
rmdir(day_dir);
|
||||
if (done && d == n_day - 1)
|
||||
{
|
||||
/* rmdir() here fails if there are stills */
|
||||
rmdir(mon_dir);
|
||||
if (done && m == n_mon - 1)
|
||||
rmdir(year_dir);
|
||||
}
|
||||
}
|
||||
if (!done)
|
||||
{
|
||||
done = still_diskfree_percent_delete(day_dir,
|
||||
PIKRELLCAM_STILL_SUBDIR, &dir_empty);
|
||||
if (dir_empty)
|
||||
{
|
||||
snprintf(del_dir, sizeof(del_dir),
|
||||
"%s/stills/.thumbs", day_dir);
|
||||
rmdir(del_dir);
|
||||
snprintf(del_dir, sizeof(del_dir),
|
||||
"%s/stills", day_dir);
|
||||
rmdir(del_dir);
|
||||
if (done && d == n_day - 1)
|
||||
{
|
||||
rmdir(mon_dir);
|
||||
if (done && m == n_mon - 1)
|
||||
rmdir(year_dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
free(day_list[d]);
|
||||
}
|
||||
|
@ -676,7 +706,7 @@ event_loop_diskusage_percent(void)
|
|||
int i, n, used_percent;
|
||||
boolean diskfree_low;
|
||||
char *loop_dir = pikrellcam.loop_dir;
|
||||
char fname[256], *s;
|
||||
char fname[500], *s;
|
||||
uint64_t used_blocks = 0, fs_blocks;
|
||||
|
||||
if ( !loop_dir
|
||||
|
|
191
src/mmalcam.c
191
src/mmalcam.c
|
@ -1,6 +1,6 @@
|
|||
/* PiKrellCam
|
||||
|
|
||||
| Copyright (C) 2015-2019 Bill Wilson billw@gkrellm.net
|
||||
| Copyright (C) 2015-2020 Bill Wilson billw@gkrellm.net
|
||||
|
|
||||
| PiKrellCam is free software: you can redistribute it and/or modify it
|
||||
| under the terms of the GNU General Public License as published by
|
||||
|
@ -34,11 +34,13 @@ extern char* mjpeg_server_queue_get(void);
|
|||
extern void mjpeg_server_queue_put(char *data, int len);
|
||||
|
||||
static boolean motion_frame_event;
|
||||
static int mjpeg_do_preview_save;
|
||||
|
||||
static pthread_mutex_t mjpeg_encoder_count_lock;
|
||||
static unsigned int mjpeg_encoder_send_count,
|
||||
mjpeg_encoder_recv_count;
|
||||
#define N_MJPEG_ENCODER_INPUT_BUFFERS 3
|
||||
|
||||
static pthread_mutex_t mjpeg_encoder_frame_count_lock;
|
||||
static unsigned int mjpeg_encoder_send_frame,
|
||||
mjpeg_encoder_recv_frame,
|
||||
mjpeg_preview_save_frame;
|
||||
|
||||
static pthread_t video_write_thread_ref;
|
||||
static int thread_ret = 1;
|
||||
|
@ -223,14 +225,14 @@ preview_save(void)
|
|||
void
|
||||
mjpeg_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
|
||||
{
|
||||
CameraObject *data = (CameraObject *) port->userdata;
|
||||
static struct timeval timer;
|
||||
int n, utime;
|
||||
static FILE *file = NULL;
|
||||
static char *fname_part;
|
||||
boolean do_preview_save = FALSE;
|
||||
static char *tcp_buf;
|
||||
static int tcp_buf_offset;
|
||||
CameraObject *data = (CameraObject *) port->userdata;
|
||||
static struct timeval timer;
|
||||
int n, utime;
|
||||
boolean do_preview_save;
|
||||
static FILE *file = NULL;
|
||||
static char *fname_part;
|
||||
static char *tcp_buf;
|
||||
static int tcp_buf_offset;
|
||||
|
||||
|
||||
if (!fname_part)
|
||||
|
@ -264,6 +266,16 @@ mjpeg_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
|
|||
tcp_buf_offset = 0;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&mjpeg_encoder_frame_count_lock);
|
||||
++mjpeg_encoder_recv_frame;
|
||||
if (mjpeg_encoder_recv_frame > mjpeg_encoder_send_frame)
|
||||
mjpeg_encoder_recv_frame = mjpeg_encoder_send_frame; /* should not happen */
|
||||
do_preview_save = (mjpeg_preview_save_frame > 0
|
||||
&& mjpeg_encoder_recv_frame >= mjpeg_preview_save_frame);
|
||||
if (do_preview_save)
|
||||
mjpeg_preview_save_frame = 0;
|
||||
pthread_mutex_unlock(&mjpeg_encoder_frame_count_lock);
|
||||
|
||||
if (pikrellcam.debug_fps && (utime = micro_elapsed_time(&timer)) > 0)
|
||||
printf("%s fps %d\n", data->name, 1000000 / utime);
|
||||
if (file)
|
||||
|
@ -271,17 +283,6 @@ mjpeg_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
|
|||
fclose(file);
|
||||
file = NULL;
|
||||
|
||||
pthread_mutex_lock(&mjpeg_encoder_count_lock);
|
||||
++mjpeg_encoder_recv_count;
|
||||
if (mjpeg_do_preview_save == 1)
|
||||
{
|
||||
mjpeg_do_preview_save = 0;
|
||||
do_preview_save = TRUE;
|
||||
}
|
||||
else if (mjpeg_do_preview_save > 1)
|
||||
--mjpeg_do_preview_save;
|
||||
pthread_mutex_unlock(&mjpeg_encoder_count_lock);
|
||||
|
||||
rename(fname_part, pikrellcam.mjpeg_filename);
|
||||
|
||||
if (do_preview_save)
|
||||
|
@ -383,77 +384,67 @@ I420_video_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
|
|||
MMAL_BUFFER_HEADER_T *buffer_in;
|
||||
static struct timeval timer;
|
||||
int utime;
|
||||
static int encoder_busy_count;
|
||||
|
||||
if ( buffer->length > 0
|
||||
&& motion_frame_event
|
||||
)
|
||||
if (buffer->length > 0 && motion_frame_event)
|
||||
{
|
||||
motion_frame_event = FALSE;
|
||||
|
||||
/* Do not send buffer to encoder if it has not received the previous
|
||||
| one we sent unless this is the frame we want for a preview save.
|
||||
| In that case, we may be sending a buffer to preview save before
|
||||
| the previous buffer is handled. This is accounted for below.
|
||||
*/
|
||||
if ( mjpeg_encoder_send_count == mjpeg_encoder_recv_count
|
||||
|| pikrellcam.do_preview_save
|
||||
)
|
||||
if (obj->callback_port_in && obj->callback_pool_in)
|
||||
{
|
||||
if (obj->callback_port_in && obj->callback_pool_in)
|
||||
buffer_in = mmal_queue_get(obj->callback_pool_in->queue);
|
||||
if ( buffer_in
|
||||
&& obj->callback_port_in->buffer_size >= buffer->length
|
||||
)
|
||||
{
|
||||
buffer_in = mmal_queue_get(obj->callback_pool_in->queue);
|
||||
if ( buffer_in
|
||||
&& obj->callback_port_in->buffer_size >= buffer->length
|
||||
)
|
||||
{
|
||||
mmal_buffer_header_mem_lock(buffer);
|
||||
memcpy(buffer_in->data, buffer->data, buffer->length);
|
||||
buffer_in->length = buffer->length;
|
||||
mmal_buffer_header_mem_unlock(buffer);
|
||||
display_draw(buffer_in->data);
|
||||
mmal_buffer_header_mem_lock(buffer);
|
||||
memcpy(buffer_in->data, buffer->data, buffer->length);
|
||||
buffer_in->length = buffer->length;
|
||||
mmal_buffer_header_mem_unlock(buffer);
|
||||
display_draw(buffer_in->data);
|
||||
|
||||
if (pikrellcam.do_preview_save)
|
||||
{
|
||||
/* If mjpeg encoder has not received previous buffer,
|
||||
| then the buffer to save will be the second buffer
|
||||
| it gets from now. Otherwise it's the next buffer.
|
||||
*/
|
||||
pthread_mutex_lock(&mjpeg_encoder_count_lock);
|
||||
if (mjpeg_encoder_send_count == mjpeg_encoder_recv_count)
|
||||
mjpeg_do_preview_save = 1;
|
||||
else
|
||||
mjpeg_do_preview_save = 2;
|
||||
pthread_mutex_unlock(&mjpeg_encoder_count_lock);
|
||||
if (mjpeg_do_preview_save == 2 && pikrellcam.debug)
|
||||
printf("%s: encoder not clear -> preview save delayed\n",
|
||||
fname_base(pikrellcam.video_pathname));
|
||||
}
|
||||
pikrellcam.do_preview_save = FALSE;
|
||||
++mjpeg_encoder_send_count;
|
||||
mmal_port_send_buffer(obj->callback_port_in, buffer_in);
|
||||
mmal_port_send_buffer(obj->callback_port_in, buffer_in);
|
||||
|
||||
pthread_mutex_lock(&mjpeg_encoder_frame_count_lock);
|
||||
++mjpeg_encoder_send_frame;
|
||||
if (pikrellcam.do_preview_save)
|
||||
mjpeg_preview_save_frame = mjpeg_encoder_send_frame;
|
||||
pthread_mutex_unlock(&mjpeg_encoder_frame_count_lock);
|
||||
|
||||
pikrellcam.do_preview_save = FALSE;
|
||||
if (pikrellcam.mjpeg_stall_count > 0)
|
||||
--pikrellcam.mjpeg_stall_count;
|
||||
if (buffer->flags & MMAL_BUFFER_HEADER_FLAG_FRAME_END)
|
||||
{
|
||||
if (pikrellcam.debug_fps && (utime = micro_elapsed_time(&timer)) > 0)
|
||||
printf("%s fps %d\n", obj->name, 1000000 / utime);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
++encoder_busy_count;
|
||||
if (pikrellcam.debug)
|
||||
printf("encoder not clear (%d) -> skipping mjpeg frame.\n",
|
||||
encoder_busy_count);
|
||||
if (encoder_busy_count > 2) /* Frame maybe dropped ??, move on */
|
||||
else /* buffer_in NULL means all encoder input buffers are
|
||||
| still in use, so mjpeg encoder is stalled.
|
||||
*/
|
||||
{
|
||||
++pikrellcam.mjpeg_stall_count;
|
||||
if (pikrellcam.do_preview_save)
|
||||
log_printf("%s: encoder is stalled -> preview save delayed\n",
|
||||
fname_base(pikrellcam.video_pathname));
|
||||
|
||||
pthread_mutex_lock(&mjpeg_encoder_frame_count_lock);
|
||||
if (mjpeg_encoder_send_frame
|
||||
> mjpeg_encoder_recv_frame + N_MJPEG_ENCODER_INPUT_BUFFERS)
|
||||
{
|
||||
/* Means a mjpeg conversion got lost in the encoder.
|
||||
| Probably should not happen.
|
||||
*/
|
||||
mjpeg_encoder_recv_frame = mjpeg_encoder_send_frame
|
||||
- N_MJPEG_ENCODER_INPUT_BUFFERS;
|
||||
}
|
||||
pthread_mutex_unlock(&mjpeg_encoder_frame_count_lock);
|
||||
|
||||
if (pikrellcam.debug)
|
||||
printf(" Syncing recv/send counts.\n");
|
||||
encoder_busy_count = 0;
|
||||
mjpeg_encoder_recv_count = mjpeg_encoder_send_count;
|
||||
printf("mjpeg encoder stalled (%d) -> skipping preview frame.\n",
|
||||
pikrellcam.mjpeg_stall_count);
|
||||
}
|
||||
}
|
||||
if (buffer->flags & MMAL_BUFFER_HEADER_FLAG_FRAME_END)
|
||||
{
|
||||
if (pikrellcam.debug_fps && (utime = micro_elapsed_time(&timer)) > 0)
|
||||
printf("%s fps %d\n", obj->name, 1000000 / utime);
|
||||
}
|
||||
}
|
||||
return_buffer_to_port(port, buffer);
|
||||
}
|
||||
|
@ -1127,11 +1118,11 @@ splitter_create(char *name, CameraObject *splitter, MMAL_PORT_T *src_port)
|
|||
boolean
|
||||
camera_create(void)
|
||||
{
|
||||
MMAL_PORT_T *port;
|
||||
MMAL_STATUS_T status;
|
||||
char *msg = "mmal_component_create";
|
||||
MMAL_PORT_T *port;
|
||||
MMAL_STATUS_T status;
|
||||
MMAL_COMPONENT_T *camera_info;
|
||||
char *msg = "mmal_component_create";
|
||||
|
||||
camera.name = "RPi camera";
|
||||
if ((status = mmal_component_create(MMAL_COMPONENT_DEFAULT_CAMERA,
|
||||
&camera.component)) == MMAL_SUCCESS)
|
||||
{
|
||||
|
@ -1148,6 +1139,32 @@ camera_create(void)
|
|||
mmal_component_destroy(camera.component);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
camera.name = strdup("ov5647"); // default to V1
|
||||
pikrellcam.camera_width_max = 2592;
|
||||
pikrellcam.camera_height_max = 1944;
|
||||
|
||||
if ((status = mmal_component_create(MMAL_COMPONENT_DEFAULT_CAMERA_INFO,
|
||||
&camera_info)) == MMAL_SUCCESS)
|
||||
{
|
||||
MMAL_PARAMETER_CAMERA_INFO_T param;
|
||||
|
||||
param.hdr.id = MMAL_PARAMETER_CAMERA_INFO;
|
||||
param.hdr.size = sizeof(param);
|
||||
status = mmal_port_parameter_get(camera_info->control, ¶m.hdr);
|
||||
if (status == MMAL_SUCCESS)
|
||||
{
|
||||
free(camera.name);
|
||||
camera.name = strdup(param.cameras[0].camera_name);
|
||||
pikrellcam.camera_width_max = (int) param.cameras[0].max_width;
|
||||
pikrellcam.camera_height_max = (int) param.cameras[0].max_height;
|
||||
}
|
||||
mmal_component_destroy(camera_info);
|
||||
}
|
||||
log_printf("camera info: %s max width: %d max height: %d\n",
|
||||
camera.name,
|
||||
pikrellcam.camera_width_max, pikrellcam.camera_height_max);
|
||||
|
||||
video_circular_buffer.h264_header_position = 0;
|
||||
|
||||
MMAL_PARAMETER_CAMERA_CONFIG_T camera_config =
|
||||
|
@ -1244,6 +1261,8 @@ jpeg_encoder_create(char *name, CameraObject *encoder,
|
|||
*/
|
||||
mmal_format_copy(in_port->format, src_port->format);
|
||||
in_port->buffer_size = src_port->buffer_size;
|
||||
if (!strcmp(name, "mjpeg_encoder"))
|
||||
in_port->buffer_num = N_MJPEG_ENCODER_INPUT_BUFFERS;
|
||||
msg = "mmal_port_format_commit(in_port)";
|
||||
status = mmal_port_format_commit(in_port);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* PiKrellCam
|
||||
|
|
||||
| Copyright (C) 2015-2019 Bill Wilson billw@gkrellm.net
|
||||
| Copyright (C) 2015-2020 Bill Wilson billw@gkrellm.net
|
||||
|
|
||||
| PiKrellCam is free software: you can redistribute it and/or modify it
|
||||
| under the terms of the GNU General Public License as published by
|
||||
|
@ -890,8 +890,11 @@ motion_frame_process(VideoCircularBuffer *vcb, MotionFrame *mf)
|
|||
|| (mf->fifo_trigger_mode & FIFO_TRIG_MODE_ENABLE)
|
||||
)
|
||||
&& !pikrellcam.servo_moving
|
||||
&& pikrellcam.zoom_motion_holdoff == 0
|
||||
&& (pikrellcam.on_preset || pikrellcam.motion_off_preset)
|
||||
);
|
||||
if (pikrellcam.zoom_motion_holdoff > 0)
|
||||
--pikrellcam.zoom_motion_holdoff;
|
||||
|
||||
if ( ( (mf->motion_status & MOTION_DETECTED)
|
||||
&& motion_enabled
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* PiKrellCam
|
||||
|
|
||||
| Copyright (C) 2015-2019 Bill Wilson billw@gkrellm.net
|
||||
| Copyright (C) 2015-2020 Bill Wilson billw@gkrellm.net
|
||||
|
|
||||
| PiKrellCam is free software: you can redistribute it and/or modify it
|
||||
| under the terms of the GNU General Public License as published by
|
||||
|
@ -129,7 +129,7 @@ multicast_message_id_repeat(char *hostname, int message_id)
|
|||
static void
|
||||
multicast_ack(char *to_host, int message_id)
|
||||
{
|
||||
char message[64];
|
||||
char message[200];
|
||||
|
||||
snprintf(message, sizeof(message), "%s ack %d", to_host, message_id);
|
||||
multicast_send("", message);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* PiKrellCam
|
||||
|
|
||||
| Copyright (C) 2015-2019 Bill Wilson billw@gkrellm.net
|
||||
| Copyright (C) 2015-2020 Bill Wilson billw@gkrellm.net
|
||||
|
|
||||
| PiKrellCam is free software: you can redistribute it and/or modify it
|
||||
| under the terms of the GNU General Public License as published by
|
||||
|
@ -1139,6 +1139,7 @@ typedef enum
|
|||
servo_cmd,
|
||||
preset_cmd,
|
||||
multicast,
|
||||
zoom,
|
||||
verbose,
|
||||
verbose_log,
|
||||
upgrade,
|
||||
|
@ -1200,6 +1201,7 @@ static Command commands[] =
|
|||
{ "preset", preset_cmd, 1, FALSE },
|
||||
{ "servo", servo_cmd, 1, FALSE },
|
||||
{ "multicast", multicast, 1, TRUE },
|
||||
{ "zoom", zoom, 1, TRUE },
|
||||
{ "verbose", verbose, 1, TRUE },
|
||||
{ "verbose_log", verbose_log, 1, TRUE },
|
||||
{ "upgrade", upgrade, 0, TRUE },
|
||||
|
@ -1215,7 +1217,7 @@ command_process(char *command_line)
|
|||
{
|
||||
VideoCircularBuffer *vcb = &video_circular_buffer;
|
||||
Command *cmd;
|
||||
char command[64], args[256], arg1[128], arg2[64], arg3[256], buf[128];
|
||||
char command[64], args[256], arg1[128], arg2[64], arg3[256], buf[300];
|
||||
char *fmt, *path;
|
||||
int i, n;
|
||||
float f;
|
||||
|
@ -1657,6 +1659,14 @@ command_process(char *command_line)
|
|||
servo_command(args);
|
||||
break;
|
||||
|
||||
case zoom:
|
||||
sscanf(args, "%d", &n);
|
||||
if (n >= 10 && n <= 100)
|
||||
zoom_percent(n);
|
||||
else
|
||||
log_printf("Bad percent arg for command: %s\n", command);
|
||||
break;
|
||||
|
||||
case verbose:
|
||||
config_set_boolean(&pikrellcam.verbose, args);
|
||||
break;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* PiKrellCam
|
||||
|
|
||||
| Copyright (C) 2015-2019 Bill Wilson billw@gkrellm.net
|
||||
| Copyright (C) 2015-2020 Bill Wilson billw@gkrellm.net
|
||||
|
|
||||
| PiKrellCam is free software: you can redistribute it and/or modify it
|
||||
| under the terms of the GNU General Public License as published by
|
||||
|
@ -57,7 +57,7 @@
|
|||
|
||||
#include "utils.h"
|
||||
|
||||
#define PIKRELLCAM_VERSION "4.3.1"
|
||||
#define PIKRELLCAM_VERSION "4.3.2"
|
||||
|
||||
|
||||
//TCP Stream Server
|
||||
|
@ -468,6 +468,15 @@ typedef struct
|
|||
|
||||
/* -------------- The Global PiKrellCam Environment -----------
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
double x,
|
||||
y,
|
||||
width,
|
||||
height;
|
||||
}
|
||||
RoiRect;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int event_gap,
|
||||
|
@ -520,7 +529,8 @@ typedef struct
|
|||
int mag_limit,
|
||||
mag_limit_count,
|
||||
burst_count,
|
||||
burst_frames;
|
||||
burst_frames,
|
||||
zoom_percent;
|
||||
SList *region_list; /* string "xf0 yf0 dxf dyf" */
|
||||
}
|
||||
PresetSettings;
|
||||
|
@ -605,7 +615,10 @@ typedef struct
|
|||
motion_magnitude_limit_count,
|
||||
motion_burst_count,
|
||||
motion_burst_frames,
|
||||
motion_record_time_limit;
|
||||
motion_record_time_limit,
|
||||
zoom_percent,
|
||||
zoom_percent_prev,
|
||||
zoom_motion_holdoff;
|
||||
|
||||
time_t motion_sync_time;
|
||||
|
||||
|
@ -641,11 +654,16 @@ typedef struct
|
|||
motion_show_counts;
|
||||
int motion_area_min_side;
|
||||
|
||||
boolean preview_stall_warning;
|
||||
|
||||
CameraConfig
|
||||
camera_config;
|
||||
CameraAdjust
|
||||
camera_adjust;
|
||||
|
||||
int camera_width_max,
|
||||
camera_height_max;
|
||||
|
||||
char *video_motion_name_format,
|
||||
*video_manual_name_format,
|
||||
*video_h264,
|
||||
|
@ -686,7 +704,8 @@ typedef struct
|
|||
int mjpeg_width,
|
||||
mjpeg_height,
|
||||
mjpeg_quality,
|
||||
mjpeg_divider;
|
||||
mjpeg_divider,
|
||||
mjpeg_stall_count;
|
||||
|
||||
char *still_name_format,
|
||||
*still_last,
|
||||
|
@ -780,6 +799,7 @@ typedef struct
|
|||
*iso,
|
||||
*metering_mode,
|
||||
*video_stabilisation,
|
||||
// *draw_focus_box,
|
||||
*exposure_compensation,
|
||||
*exposure_mode,
|
||||
*white_balance,
|
||||
|
@ -913,6 +933,9 @@ boolean mmalcam_config_parameter_set(char *name, char *value, boolean set_camer
|
|||
CameraParameter
|
||||
*mmalcam_config_parameter_get(char *name);
|
||||
|
||||
|
||||
void zoom_percent(int percent);
|
||||
|
||||
extern boolean config_load(char *config_file);
|
||||
extern void config_save(char *config_file);
|
||||
extern void config_set_defaults(char *homedir);
|
||||
|
@ -963,6 +986,7 @@ void display_command(char *cmd_line);
|
|||
void display_draw(uint8_t *i420);
|
||||
void display_inform(char *args);
|
||||
void display_inform_clear(void);
|
||||
void display_motion_limit_adjustment_sync(PresetSettings *settings);
|
||||
|
||||
void display_quit(void);
|
||||
|
||||
|
|
18
src/preset.c
18
src/preset.c
|
@ -1,7 +1,7 @@
|
|||
|
||||
/* PiKrellCam
|
||||
|
|
||||
| Copyright (C) 2015-2019 Bill Wilson billw@gkrellm.net
|
||||
| Copyright (C) 2015-2020 Bill Wilson billw@gkrellm.net
|
||||
|
|
||||
| PiKrellCam is free software: you can redistribute it and/or modify it
|
||||
| under the terms of the GNU General Public License as published by
|
||||
|
@ -258,6 +258,9 @@ preset_load_values(boolean do_pan)
|
|||
pikrellcam.motion_magnitude_limit_count = settings->mag_limit_count;
|
||||
pikrellcam.motion_burst_count = settings->burst_count;
|
||||
pikrellcam.motion_burst_frames = settings->burst_frames;
|
||||
pikrellcam.zoom_percent = settings->zoom_percent;
|
||||
zoom_percent(pikrellcam.zoom_percent);
|
||||
display_motion_limit_adjustment_sync(settings);
|
||||
}
|
||||
save_show = mf->show_preset;
|
||||
motion_command("delete_regions all");
|
||||
|
@ -311,6 +314,7 @@ preset_settings_set_modified(void)
|
|||
settings->mag_limit_count = pikrellcam.motion_magnitude_limit_count;
|
||||
settings->burst_count = pikrellcam.motion_burst_count;
|
||||
settings->burst_frames = pikrellcam.motion_burst_frames;
|
||||
settings->zoom_percent = pikrellcam.zoom_percent;
|
||||
pikrellcam.preset_modified = TRUE;
|
||||
}
|
||||
}
|
||||
|
@ -387,6 +391,7 @@ preset_new(PresetPosition *pos_src)
|
|||
settings->mag_limit_count = settings_src->mag_limit_count;
|
||||
settings->burst_count = settings_src->burst_count;
|
||||
settings->burst_frames = settings_src->burst_frames;
|
||||
settings->zoom_percent = settings_src->zoom_percent;
|
||||
for (rlist = settings_src->region_list; rlist; rlist = rlist->next)
|
||||
{
|
||||
region = strdup((char *) rlist->data);
|
||||
|
@ -408,6 +413,7 @@ preset_new(PresetPosition *pos_src)
|
|||
settings->mag_limit_count = pikrellcam.motion_magnitude_limit_count;
|
||||
settings->burst_count = pikrellcam.motion_burst_count;
|
||||
settings->burst_frames = pikrellcam.motion_burst_frames;
|
||||
settings->zoom_percent = pikrellcam.zoom_percent;
|
||||
preset_settings_regions_set(settings);
|
||||
preset_notify(18);
|
||||
}
|
||||
|
@ -539,7 +545,10 @@ preset_command(char *cmd_line)
|
|||
preset_notify(18);
|
||||
}
|
||||
else
|
||||
{
|
||||
preset_notify(10);
|
||||
zoom_percent(pikrellcam.zoom_percent);
|
||||
}
|
||||
}
|
||||
else
|
||||
preset_load_values(TRUE);
|
||||
|
@ -560,7 +569,10 @@ preset_command(char *cmd_line)
|
|||
preset_notify(18);
|
||||
}
|
||||
else
|
||||
{
|
||||
preset_notify(10);
|
||||
zoom_percent(pikrellcam.zoom_percent);
|
||||
}
|
||||
}
|
||||
else
|
||||
preset_load_values(TRUE);
|
||||
|
@ -742,6 +754,7 @@ preset_config_load(void)
|
|||
settings = calloc(1, sizeof(PresetSettings));
|
||||
pos->settings_list = slist_append(pos->settings_list, settings);
|
||||
pos->n_settings += 1;
|
||||
settings->zoom_percent = 100;
|
||||
continue;
|
||||
}
|
||||
if (!settings)
|
||||
|
@ -760,6 +773,8 @@ preset_config_load(void)
|
|||
sscanf(buf + 12, "%d", &settings->burst_count);
|
||||
else if (!strncmp(buf, "burst_frames", 12))
|
||||
sscanf(buf + 13, "%d", &settings->burst_frames);
|
||||
else if (!strncmp(buf, "zoom_percent", 12))
|
||||
sscanf(buf + 13, "%d", &settings->zoom_percent);
|
||||
else if (!strncmp(buf, "add_region", 10))
|
||||
{
|
||||
region = strdup(buf); /* string "add_region xf0 yf0 dxf dyf" */
|
||||
|
@ -797,6 +812,7 @@ preset_config_save(void)
|
|||
fprintf(f, "magnitude_count %d\n", settings->mag_limit_count);
|
||||
fprintf(f, "burst_count %d\n", settings->burst_count);
|
||||
fprintf(f, "burst_frames %d\n", settings->burst_frames);
|
||||
fprintf(f, "zoom_percent %d\n", settings->zoom_percent);
|
||||
for (rlist = settings->region_list; rlist; rlist = rlist->next)
|
||||
{
|
||||
region = (char *) rlist->data; /* string "add_region xf0 yf0 dxf dyf" */
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
/* PiKrellCam
|
||||
|
|
||||
| Copyright (C) 2015-2019 Bill Wilson billw@gkrellm.net
|
||||
| Copyright (C) 2015-2020 Bill Wilson billw@gkrellm.net
|
||||
|
|
||||
| PiKrellCam is free software: you can redistribute it and/or modify it
|
||||
| under the terms of the GNU General Public License as published by
|
||||
|
|
44
www/help.php
44
www/help.php
|
@ -70,6 +70,14 @@ And there is a Raspberry Pi
|
|||
<span style='font-size: 1.5em; font-weight: 650;'>Recent Release Notes</span><hr>
|
||||
<div class='indent0'>
|
||||
|
||||
Version 4.3.2
|
||||
<div class='indent1'>
|
||||
Detect camera to determine resolution options shown in GUI and added
|
||||
resolutions for HQ camera.<br>
|
||||
Setup->Preset->Settings-><a href="help.php#ZOOM_PERCENT">Zoom_Percent.</a><br>
|
||||
Setup->Config->Settings-><a href="help.php#STALL_WARNING">Preview_Stall_Warning.</a>
|
||||
</div>
|
||||
<br>
|
||||
Version 4.3.1 - video_mp4box_fps can be fractional. For audio/video drift
|
||||
tuning.
|
||||
<br>
|
||||
|
@ -828,6 +836,19 @@ Preset group and there will be no Servo button in the Config group.
|
|||
field of view. Set the value higher to decrease detection of large objects passing
|
||||
quickly through the field of view.
|
||||
</li>
|
||||
<a name="ZOOM_PERCENT">
|
||||
<p>
|
||||
<li><span style='font-weight:700'>Zoom_Percent</span> -
|
||||
is the percent width and height of the camera sensor used for
|
||||
imaging. Set the percent lower to digitally zoom in for videos
|
||||
and stills. Moderate zooming can tune the camera field of view
|
||||
at the expense of some resolution as fewer pixels may be used to
|
||||
convert to stills or videos.
|
||||
While viewing the web page preview, a larger zoom (lower percent
|
||||
value) magnifies the pixels and is useful for camera focusing.<br>
|
||||
If a zoom value is selected, it is saved as part of the current
|
||||
preset along with the motion limit and motion region settings.
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<p>
|
||||
|
@ -1064,6 +1085,27 @@ Preset group and there will be no Servo button in the Config group.
|
|||
is normally not desirable, so the option should be set
|
||||
<span style='font-weight:700'>ON</span>.
|
||||
</li>
|
||||
<a name="STALL_WARNING">
|
||||
<p>
|
||||
<li><span style='font-weight:700'>Preview_Stall_Warning</span>
|
||||
- default is
|
||||
<span style='font-weight:700'>ON</span>.
|
||||
Enable showing a warning on the web preview if the preview jpeg
|
||||
encoder stalls when hitting GPU performance limits which cause
|
||||
preview frames to be lost.
|
||||
The solution is to lower video_fps until the stalls stop or at
|
||||
least become infrequent.
|
||||
This strangely seems more an issue (at least with current
|
||||
firmware) with the HQ camera on the Pi 4. With an HQ camera
|
||||
on a Pi 4 I needed to lower video_fps to 20 to avoid stalls,
|
||||
but on a P2 the HQ camera ran without stalls at video_fps 24.
|
||||
I've not seen this issue with V1 or V2 cameras.<br>
|
||||
If this option is
|
||||
<span style='font-weight:700'>OFF</span>,
|
||||
the warning is still enabled when showing preset information
|
||||
with the
|
||||
<span style='font-weight:700'>Show: Preset</span> button.
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<p>
|
||||
|
@ -1993,6 +2035,8 @@ preset prev_settings
|
|||
preset next_settings
|
||||
preset goto position settings
|
||||
|
||||
zoom percent - percent is 10-100
|
||||
|
||||
display [command] - commands sent by the web page to display OSD menus. Not intended for
|
||||
script or command line use.
|
||||
|
||||
|
|
Loading…
Reference in New Issue