Read about our upcoming Code of Conduct on this issue

Commit 0ba9b2ab authored by Alex's avatar Alex
Browse files

Merged in raw_fixes (pull request #828)

Raw fixes part 5

--HG--
branch : unified
......@@ -63,6 +63,7 @@
#include "beep.h"
#include "raw.h"
#include "zebra.h"
#include "focus.h"
#include "fps.h"
#include "../mlv_rec/mlv.h"
#include "../trace/trace.h"
......@@ -121,9 +122,9 @@ static CONFIG_INT("raw.dolly", dolly_mode, 0);
#define FRAMING_PANNING (dolly_mode == 1)
static CONFIG_INT("raw.preview", preview_mode, 0);
#define PREVIEW_AUTO (preview_mode == 0)
#define PREVIEW_CANON (preview_mode == 1)
#define PREVIEW_ML (preview_mode == 2)
#define PREVIEW_AUTO (preview_mode == 0)
#define PREVIEW_CANON (preview_mode == 1)
#define PREVIEW_ML (preview_mode == 2)
#define PREVIEW_HACKED (preview_mode == 3)
static CONFIG_INT("raw.warm.up", warm_up, 0);
......@@ -245,18 +246,24 @@ static void refresh_cropmarks()
}
}
static int calc_res_y(int res_x, int num, int den, float squeeze)
static int calc_res_y(int res_x, int max_res_y, int num, int den, float squeeze)
{
int res_y;
if (squeeze != 1.0f)
{
/* image should be enlarged vertically in post by a factor equal to "squeeze" */
return (int)(roundf(res_x * den / num / squeeze) + 1) & ~1;
res_y = (int)(roundf(res_x * den / num / squeeze) + 1);
}
else
{
/* assume square pixels */
return (res_x * den / num + 1) & ~1;
res_y = (res_x * den / num + 1);
}
res_y = MIN(res_y, max_res_y);
return res_y & ~1;
}
static void update_cropping_offsets()
......@@ -325,7 +332,7 @@ static void update_resolution_params()
/* res Y */
int num = aspect_ratio_presets_num[aspect_ratio_index];
int den = aspect_ratio_presets_den[aspect_ratio_index];
res_y = MIN(calc_res_y(res_x, num, den, squeeze_factor), max_res_y);
res_y = calc_res_y(res_x, max_res_y, num, den, squeeze_factor);
/* frame size */
/* should be multiple of 512, so there's no write speed penalty (see http://chdk.setepontos.com/index.php?topic=9970 ; confirmed by benchmarks) */
......@@ -352,8 +359,8 @@ static char* guess_aspect_ratio(int res_x, int res_y)
float ratio = (float)res_x / res_y;
float minerr = 100;
/* common ratios that are expressed as integer numbers, e.g. 3:2, 16:9, but not 2.35:1 */
static int common_ratios_x[] = {1, 2, 3, 3, 4, 16, 5, 5};
static int common_ratios_y[] = {1, 1, 1, 2, 3, 9, 4, 3};
static int common_ratios_x[] = {1, 2, 3, 4, 5, 3, 4, 16, 5, 5};
static int common_ratios_y[] = {1, 1, 1, 1, 1, 2, 3, 9, 4, 3};
for (int i = 0; i < COUNT(common_ratios_x); i++)
{
int num = common_ratios_x[i];
......@@ -369,7 +376,7 @@ static char* guess_aspect_ratio(int res_x, int res_y)
if (minerr < 0.05)
{
int h = calc_res_y(res_x, best_num, best_den, squeeze_factor);
int h = calc_res_y(res_x, max_res_y, best_num, best_den, squeeze_factor);
/* if the difference is 1 pixel, consider it exact */
char* qualifier = ABS(h - res_y) > 1 ? "almost " : "";
snprintf(msg, sizeof(msg), "%s%d:%d", qualifier, best_num, best_den);
......@@ -378,14 +385,14 @@ static char* guess_aspect_ratio(int res_x, int res_y)
{
int r = (int)roundf(ratio * 100);
/* is it 2.35:1 or 2.353:1? */
int h = calc_res_y(res_x, r, 100, squeeze_factor);
int h = calc_res_y(res_x, max_res_y, r, 100, squeeze_factor);
char* qualifier = ABS(h - res_y) > 1 ? "almost " : "";
if (r%100) snprintf(msg, sizeof(msg), "%s%d.%02d:1", qualifier, r/100, r%100);
}
else
{
int r = (int)roundf((1/ratio) * 100);
int h = calc_res_y(res_x, 100, r, squeeze_factor);
int h = calc_res_y(res_x, max_res_y, 100, r, squeeze_factor);
char* qualifier = ABS(h - res_y) > 1 ? "almost " : "";
if (r%100) snprintf(msg, sizeof(msg), "%s1:%d.%02d", qualifier, r/100, r%100);
}
......@@ -524,13 +531,19 @@ static MENU_UPDATE_FUNC(aspect_ratio_update_info)
{
char* ratio = guess_aspect_ratio(res_x, res_y);
MENU_SET_HELP("%dx%d (%s).", res_x, res_y, ratio);
if (!streq(ratio, info->value))
{
/* aspect ratio different from requested value? */
MENU_SET_RINFO("%s", ratio);
}
}
else
{
int num = aspect_ratio_presets_num[aspect_ratio_index];
int den = aspect_ratio_presets_den[aspect_ratio_index];
int sq100 = (int)roundf(squeeze_factor*100);
int res_y_corrected = calc_res_y(res_x, num, den, 1.0f);
int res_y_corrected = calc_res_y(res_x, max_res_y*squeeze_factor, num, den, 1.0f);
MENU_SET_HELP("%dx%d. Stretch by %s%d.%02dx to get %dx%d (%s) in post.", res_x, res_y, FMT_FIXEDPOINT2(sq100), res_x, res_y_corrected, aspect_ratio_choices[aspect_ratio_index]);
}
}
......@@ -623,7 +636,7 @@ static MENU_UPDATE_FUNC(aspect_ratio_update)
int num = aspect_ratio_presets_num[aspect_ratio_index];
int den = aspect_ratio_presets_den[aspect_ratio_index];
int selected_y = calc_res_y(res_x, num, den, squeeze_factor);
int selected_y = calc_res_y(res_x, max_res_y, num, den, squeeze_factor);
if (selected_y > max_res_y + 2)
{
......@@ -1093,7 +1106,7 @@ static void cache_require(int lock)
static void unhack_liveview_vsync(int unused);
static void hack_liveview_vsync()
static void FAST hack_liveview_vsync()
{
if (cam_5d2 || cam_50d)
{
......@@ -1151,7 +1164,6 @@ static void hack_liveview_vsync()
if (should_hack)
{
int y = 100;
for (int channel = 0; channel < 32; channel++)
{
/* silence out the EDMACs used for HD and LV buffers */
......@@ -1159,7 +1171,7 @@ static void hack_liveview_vsync()
if (pitch == vram_lv.pitch || pitch == vram_hd.pitch)
{
uint32_t reg = edmac_get_base(channel);
bmp_printf(FONT_SMALL, 30, y += font_small.height, "Hack %x %dx%d ", reg, shamem_read(reg + 0x10) & 0xFFFF, shamem_read(reg + 0x10) >> 16);
//printf("Hack %d %x %dx%d\n", channel, reg, shamem_read(reg + 0x10) & 0xFFFF, shamem_read(reg + 0x10) >> 16);
*(volatile uint32_t *)(reg + 0x10) = shamem_read(reg + 0x10) & 0xFFFF;
}
}
......@@ -1176,6 +1188,9 @@ static void unhack_liveview_vsync(int unused)
while (!RAW_IS_IDLE) msleep(100);
PauseLiveView();
ResumeLiveView();
/* fixme: in exmem.c, but how? */
gui_uilock(UILOCK_NONE);
}
static void hack_liveview(int unhack)
......@@ -2168,11 +2183,12 @@ static struct menu_entry raw_video_menu[] =
.name = "Preview",
.priv = &preview_mode,
.max = 3,
.choices = CHOICES("Auto", "Canon", "ML Grayscale", "HaCKeD"),
.choices = CHOICES("Auto", "Real-time", "Framing", "Frozen LV"),
.help = "Raw video preview (long half-shutter press to override):",
.help2 = "Auto: ML chooses what's best for each video mode\n"
"Canon: plain old LiveView. Framing is not always correct.\n"
"ML Grayscale: looks ugly, but at least framing is correct.\n"
"HaCKeD: try to squeeze a little speed by killing LiveView.\n",
"Plain old LiveView (color and real-time). Framing is not always correct.\n"
"Slow (not real-time) and low-resolution, but has correct framing.\n"
"Freeze LiveView for more speed; uses 'Framing' preview if Global Draw ON.\n",
.advanced = 1,
},
{
......@@ -2337,19 +2353,74 @@ static int raw_rec_should_preview(void)
/* keep x10 mode unaltered, for focusing */
if (lv_dispsize == 10) return 0;
if (PREVIEW_AUTO)
/* enable preview in x5 mode, since framing doesn't match */
return lv_dispsize == 5;
else if (PREVIEW_CANON)
/* framing is incorrect in modes with high resolutions
* (e.g. x5 zoom, crop_rec) */
int raw_active_width = raw_info.active_area.x2 - raw_info.active_area.x1;
int raw_active_height = raw_info.active_area.y2 - raw_info.active_area.y1;
int framing_incorrect =
raw_active_width > 2000 ||
raw_active_height > (video_mode_fps <= 30 ? 1300 : 720);
/* some modes have Canon preview totally broken */
int preview_broken = (lv_dispsize == 1 && raw_active_width > 2000);
int prefer_framing_preview =
(res_x < max_res_x * 80/100) ? 1 : /* prefer correct framing instead of large black bars */
(res_x*9 < res_y*16) ? 1 : /* tall aspect ratio -> prevent image hiding under info bars*/
(framing_incorrect) ? 1 : /* use correct framing in modes where Canon preview is incorrect */
0 ; /* otherwise, use plain LiveView */
/* only override on long half-shutter press, when not autofocusing */
/* todo: move these in core, with a proper API */
static int long_halfshutter_press = 0;
static int last_hs_unpress = 0;
static int autofocusing = 0;
if (!get_halfshutter_pressed())
{
autofocusing = 0;
long_halfshutter_press = 0;
last_hs_unpress = get_ms_clock_value();
}
else
{
if (lv_focus_status == 3)
{
autofocusing = 1;
}
if (get_ms_clock_value() - last_hs_unpress > 500)
{
long_halfshutter_press = 1;
}
}
if (autofocusing)
{
/* disable our preview during autofocus */
return 0;
}
if (PREVIEW_AUTO)
{
/* half-shutter overrides default choice */
if (preview_broken) return 1;
return prefer_framing_preview ^ long_halfshutter_press;
}
else if (PREVIEW_CANON)
{
return long_halfshutter_press;
}
else if (PREVIEW_ML)
return 1;
{
return !long_halfshutter_press;
}
else if (PREVIEW_HACKED)
return RAW_IS_RECORDING || get_halfshutter_pressed() || lv_dispsize == 5;
{
if (preview_broken) return 1;
return (RAW_IS_RECORDING || prefer_framing_preview)
^ long_halfshutter_press;
}
return 0;
}
......@@ -2368,27 +2439,40 @@ static unsigned int raw_rec_update_preview(unsigned int ctx)
}
return enabled;
}
/* only consider speed when the recorder is actually busy */
int queued_frames = MOD(writing_queue_tail - writing_queue_head, COUNT(writing_queue));
int need_for_speed = (RAW_IS_RECORDING) && (
(PREVIEW_HACKED && queued_frames > slot_count / 8) ||
(queued_frames > slot_count / 4)
);
struct display_filter_buffers * buffers = (struct display_filter_buffers *) ctx;
raw_previewing = 1;
raw_set_preview_rect(skip_x, skip_y, res_x, res_y);
raw_set_preview_rect(skip_x, skip_y, res_x, res_y, 1);
raw_force_aspect_ratio_1to1();
/* when recording, preview both full-size buffers,
* to make sure it's not recording every other frame */
static int fi = 0; fi = !fi;
raw_preview_fast_ex(
(void*)-1,
PREVIEW_HACKED && RAW_RECORDING ? (void*)-1 : buffers->dst_buf,
RAW_IS_RECORDING ? fullsize_buffers[fi] : (void*)-1,
PREVIEW_HACKED && RAW_IS_RECORDING ? (void*)-1 : buffers->dst_buf,
-1,
-1,
get_halfshutter_pressed() ? RAW_PREVIEW_COLOR_HALFRES : RAW_PREVIEW_GRAY_ULTRA_FAST
(need_for_speed && !get_halfshutter_pressed())
? RAW_PREVIEW_GRAY_ULTRA_FAST
: RAW_PREVIEW_COLOR_HALFRES
);
raw_previewing = 0;
if (!RAW_IS_IDLE)
{
/* be gentle with the CPU, save it for recording (especially if the buffer is almost full) */
//~ msleep(free_buffers <= 2 ? 2000 : used_buffers > 1 ? 1000 : 100);
msleep(1000);
}
/* be gentle with the CPU, save it for recording (especially if the buffer is almost full) */
msleep(
(need_for_speed)
? ((queued_frames > slot_count / 2) ? 1000 : 500)
: 50
);
preview_dirty = 1;
return 1;
......
......@@ -4157,7 +4157,7 @@ static unsigned int raw_rec_update_preview(unsigned int ctx)
struct display_filter_buffers * buffers = (struct display_filter_buffers *) ctx;
raw_previewing = 1;
raw_set_preview_rect(skip_x, skip_y, res_x, res_y);
raw_set_preview_rect(skip_x, skip_y, res_x, res_y, 1);
raw_force_aspect_ratio_1to1();
raw_preview_fast_ex(
(void*)-1,
......
......@@ -6,7 +6,7 @@
#define LEDON 0x138800
#define LEDOFF 0x838C00
#define CARD_A_MAKER 0x68D24
#define CARD_A_MAKER 0x68D23
#define CARD_A_MODEL 0x68D57
//~ #define CARD_A_LABEL 0x26E000 not good
//need to find
......
......@@ -286,6 +286,7 @@ DIET_OBJ = \
strtol.o \
strtoul.o \
strchr.o \
strstr.o \
memcmp.o \
memmove.o \
atoi.o \
......
......@@ -757,18 +757,28 @@ int fps_get_current_x1000()
return fps_x1000;
}
static void calc_rolling_shutter(int * line_ns, int * frame_us, int * frame_percent, int * xres, int * yres);
static MENU_UPDATE_FUNC(fps_print)
{
static int last_inactive = 0;
int t = get_ms_clock_value_fast();
int frame_readout_time_percent;
calc_rolling_shutter(0, 0, &frame_readout_time_percent, 0, 0);
if (fps_override)
{
int current_fps = fps_get_current_x1000();
MENU_SET_VALUE("%d.%03d",
current_fps/1000, current_fps%1000
);
if (frame_readout_time_percent)
{
MENU_SET_RINFO("Roll.sh.%d%%", frame_readout_time_percent);
}
/* FPS override will disable sound recording automatically, but not right away (only at next update step) */
/* if it can't be disabled automatically (timeout 1 second), show a warning so the user can disable it himself */
if (sound_recording_enabled_canon() && is_movie_mode() && fps_should_disable_sound() && t > last_inactive + 1000)
......@@ -782,8 +792,18 @@ static MENU_UPDATE_FUNC(fps_print)
else
{
last_inactive = t;
}
int current_fps = fps_get_current_x1000();
MENU_SET_RINFO("%d.%03d",
current_fps/1000, current_fps%1000
);
if (frame_readout_time_percent)
{
MENU_APPEND_RINFO(", Rs.%d%%", frame_readout_time_percent);
}
}
#ifdef CONFIG_7D
if (is_movie_mode() && !raw_lv_is_enabled())
{
......@@ -822,7 +842,7 @@ static MENU_UPDATE_FUNC(desired_fps_print)
MENU_SET_WARNING(MENU_WARN_NOT_WORKING, "FPS value is computed from photo shutter speed.");
}
static MENU_UPDATE_FUNC(rolling_shutter_print)
static void calc_rolling_shutter(int * line_ns, int * frame_us, int * frame_percent, int * xres, int * yres)
{
/* Timer A tells us how fast the rows are read out */
/* Timer A / main clock = time for reading one line */
......@@ -830,12 +850,8 @@ static MENU_UPDATE_FUNC(rolling_shutter_print)
int main_clock_div_timer_A = get_current_tg_freq();
float line_readout_time_us = 1.0e9f / main_clock_div_timer_A;
int line_readout_time_us_x10 = (int)roundf(line_readout_time_us * 10.0f);
if (line_ns) *line_ns = (int)roundf(line_readout_time_us * 1000.0f);
/* since we don't know exactly the recording resolution, that's the only reliable value that we can display */
MENU_SET_VALUE("%s%d.%d "SYM_MICRO"s / line", FMT_FIXEDPOINT1(line_readout_time_us_x10));
int vertical_res = 0;
int horizontal_res = 0;
......@@ -859,6 +875,30 @@ static MENU_UPDATE_FUNC(rolling_shutter_print)
vertical_res = MIN(vertical_res, vertical_res_16_9);
}
}
if (xres) *xres = horizontal_res;
if (yres) *yres = vertical_res;
if (frame_us) *frame_us = 0;
if (frame_percent) *frame_percent = 0;
if (vertical_res)
{
int frame_duration_us = (int)roundf(1e9 / fps_get_current_x1000());
if (frame_us) *frame_us = line_readout_time_us * vertical_res;
if (frame_percent) *frame_percent = (int)roundf(line_readout_time_us * vertical_res * 100 / frame_duration_us);
}
}
static MENU_UPDATE_FUNC(rolling_shutter_print)
{
int line_readout_time_ns, frame_readout_time_us, frame_readout_time_percent, horizontal_res, vertical_res;
calc_rolling_shutter(&line_readout_time_ns, &frame_readout_time_us, &frame_readout_time_percent, &horizontal_res, &vertical_res);
int line_readout_time_us_x10 = line_readout_time_ns / 100;
/* since we don't know exactly the recording resolution, that's the only reliable value that we can display */
MENU_SET_VALUE("%s%d.%d "SYM_MICRO"s / line", FMT_FIXEDPOINT1(line_readout_time_us_x10));
/* trick to display status messages even with FPS override turned off */
int old_warn = info->warning_level;
......@@ -866,9 +906,13 @@ static MENU_UPDATE_FUNC(rolling_shutter_print)
if (vertical_res)
{
int rolling_shutter_ms_x10 = (int)roundf(line_readout_time_us * vertical_res / 100.0f);
int rolling_shutter_ms_x10 = frame_readout_time_us / 100;
MENU_SET_WARNING(MAX(MENU_WARN_INFO, old_warn), "Rolling shutter: %s%d.%d ms at %dx%d.", FMT_FIXEDPOINT1(rolling_shutter_ms_x10), horizontal_res, vertical_res);
MENU_SET_WARNING(MAX(MENU_WARN_INFO, old_warn), "Rolling shutter: %s%d.%d ms (%d%%) at %dx%d.",
FMT_FIXEDPOINT1(rolling_shutter_ms_x10),
frame_readout_time_percent, 0,
horizontal_res, vertical_res
);
}
else
{
......@@ -1651,19 +1695,23 @@ static void fps_task()
continue;
}
int default_fps = calc_fps_x1000(fps_timer_a_orig, fps_timer_b_orig);
int f = fps_values_x1000[fps_override_index];
if (fps_sync_shutter && !is_movie_mode())
{
int default_fps = calc_fps_x1000(fps_timer_a_orig, fps_timer_b_orig);
f = MIN(1000000 / raw2shutter_ms(lens_info.raw_shutter), default_fps);
}
if (lv_dispsize == 10 && get_halfshutter_pressed())
{
/* x10 zoom - disable FPS override to check focus */
f = default_fps;
}
#ifdef FEATURE_FPS_RAMPING
if (FPS_RAMP) // artistic effect - http://www.magiclantern.fm/forum/index.php?topic=2963.0
{
int default_fps = calc_fps_x1000(fps_timer_a_orig, fps_timer_b_orig);
f = MIN(f, default_fps); // no overcranking possible with FPS ramping
int total_duration = fps_ramp_timings[fps_ramp_duration];
......
......@@ -436,7 +436,12 @@ static int raw_lv_get_resolution(int* width, int* height)
/* height may be a little different; 5D3 needs to subtract 1,
* EOS M needs to add 1, 100D usually gives exact value
* is it really important to have exact height? */
* is it really important to have exact height?
* for some raw types, yes! */
#ifdef CONFIG_5D3
(*height)--;
#endif
#ifdef CONFIG_EOSM
/* EOS M exception */
......@@ -981,7 +986,7 @@ static int preview_rect_y;
static int preview_rect_w;
static int preview_rect_h;
void raw_set_preview_rect(int x, int y, int w, int h)
void raw_set_preview_rect(int x, int y, int w, int h, int obey_info_bars)
{
preview_rect_x = x;
preview_rect_y = y;
......@@ -994,13 +999,17 @@ void raw_set_preview_rect(int x, int y, int w, int h)
/* not exactly a good idea when we have already acquired raw_sem */
//~ get_yuv422_vram(); // update vram parameters
/* fixme: handle different screen layouts */
int top_margin = (obey_info_bars) ? 38 : 0;
int bottom_margin = (obey_info_bars) ? 38 : 0;
/* scaling factor: raw width should match os.x_ex, same for raw height and os.y_ex */
lv2raw.sx = 1024 * w / BM2LV_DX(os.x_ex);
lv2raw.sy = 1024 * h / BM2LV_DY(os.y_ex);
lv2raw.sy = 1024 * h / BM2LV_DY(os.y_ex - top_margin - bottom_margin);
/* translation: raw top-left corner (x,y) should match (os.x0,os.y0) */
int x0_lv = BM2LV_X(os.x0);
int y0_lv = BM2LV_Y(os.y0);
int y0_lv = BM2LV_Y(os.y0 + top_margin);
lv2raw.tx = x - LV2RAW_DX(x0_lv);
lv2raw.ty = y - LV2RAW_DY(y0_lv);
}
......@@ -1073,7 +1082,7 @@ void raw_set_geometry(int width, int height, int skip_left, int skip_right, int
}
#endif
raw_set_preview_rect(preview_skip_left, preview_skip_top, preview_width, preview_height);
raw_set_preview_rect(preview_skip_left, preview_skip_top, preview_width, preview_height, 0);
dbg_printf("lv2raw sx:%d sy:%d tx:%d ty:%d\n", lv2raw.sx, lv2raw.sy, lv2raw.tx, lv2raw.ty);
dbg_printf("raw2lv test: (%d,%d) - (%d,%d)\n", RAW2LV_X(raw_info.active_area.x1), RAW2LV_Y(raw_info.active_area.y1), RAW2LV_X(raw_info.active_area.x2), RAW2LV_Y(raw_info.active_area.y2));
......
......@@ -144,7 +144,7 @@ int raw_lv_settings_still_valid();
void raw_set_geometry(int width, int height, int skip_left, int skip_right, int skip_top, int skip_bottom);
void raw_force_aspect_ratio_1to1();
void raw_set_preview_rect(int x, int y, int w, int h);
void raw_set_preview_rect(int x, int y, int w, int h, int obey_info_bars);
/* call this after you have altered the preview settings, and you want to restore the original ones */
void raw_set_dirty(void);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment