Magic Lantern Forum

Developing Magic Lantern => General Development => Topic started by: Morghus on March 04, 2014, 12:46:37 AM

Title: Auto ETTR on EOSM
Post by: Morghus on March 04, 2014, 12:46:37 AM
Alright since I wanted to use my EOS M as a secondary timelapse camera I wanted to fix ETTR on it and finally dive into ML hacking. Here are a few things I discovered so far:


I'm stuck here... the quick fix would be to use the *_slow functions obviously, but it must be possible to fix auto_ettr_vsync_cbr(). I'd really appreciate it if someone pointed me into the right direction as this is my first time diving into ML code and I have no clue where to start. Is it possible that LV just behaves differently in movie mode? Can I put the camera into this mode if that's true? What other possibilities should I look into?
Title: Re: Auto ETTR on EOSM
Post by: a1ex on March 04, 2014, 09:04:53 AM
That's a great start. Indeed, the key to fast ETTR in LiveView is to be able to change shuter speeds via FRAME_SHUTTER_TIMER (simply by setting it to some constant value from a vsync CBR). Also see this explanation: http://www.magiclantern.fm/forum/index.php?topic=9741.msg101808#msg101808

So, I would start by checking Canon's values at different shutter speeds, but considering EOS-M's quirks, I would do that while recording H.264. Then, you can cross-check the values with standby and photo modes, take into account the ExpSim mechanism, and see if you can get something useful out of it. In any case, FRAME_BV should indicate the overall exposure (8 units = 1 EV), and changes in FRAME_SHUTTER_TIMER should be consistent with changes in FRAME_SHUTTER. So, feel free to create a table with some values from these macros.

You may need to program directly in the core to access these macros, or copy their definition in the module while investigating.

Next, you should try to override these things; for ETTR, we are interested in overriding ISO (FRAME_ISO) and shutter speed (FRAME_SHUTTER_TIMER, which behaves like 1/exposure_time).

If it works, but it's changing smoothly, something's fishy. You might try to use exposure override, double-check the vsync input/state in the state transition (but this one looks OK from here), or hexdump the memory starting from VIDEO_PARAMETERS_SRC_3 and try to identify some more exposure variables (change Canon settings and see which offsets change).
Title: Re: Auto ETTR on EOSM
Post by: Morghus on March 04, 2014, 09:49:10 PM
Thanks for your guidance so far, I did what you suggested:



I'm not really sure what happens there though. I can see where FRAME_ISO, FRAME_APERTURE, FRAME_SHUTTER and FRAME_SHUTTER_TIMER come from but setting FRAME_ISO or FRAME_SHUTTER_TIMER does not seem to have an effect. Every time the digit left of FRAME_BV changes, FRAME_ISO is set to ISO_100 or ISO_800 and you can see it change in the dump for a frame, LV does not seem to be affected though.

It's only smoothing in photo mode, in movie mode or with Expo. Override on it does not smooth the changes. Any other suggestions where I can poke at?



Title: Re: Auto ETTR on EOSM
Post by: a1ex on March 04, 2014, 10:05:25 PM
So... setting FRAME_ISO and FRAME_SHUTTER_TIMER have no effect, but HDR video works. To be clear:

- did you try HDR video with ISO or also the advanced one with shutter?
- are these two things working in movie mode?
- are these two things working in expo override mode?

If the last answer is yes, you could try enabling expo override temporarily, from auto_ettr_prepare_lv. Look for "workaround for Canon's manual lens underexposure bug" and try using that for photo mode.

There is also a test in AUTO_ETTR_DEBUG; that one tests the vsync mechanism and checks if the exposure is indeed altered as requested (e.g. you request darkening by X EV, you get an image actually darker by X EV +/- a small measurement error).

This test should probably be moved to core code, in Debug menu, or maybe in raw_diag, to check this backend support everywhere (would cover LV RAW histogram, set_frame_iso/set_frame_shutter_timer and the vsync hook).
Title: Re: Auto ETTR on EOSM
Post by: Morghus on March 04, 2014, 10:37:04 PM
Quick update to answer those three questions:



Expo override does not fix it.
While HDR video is doing its thing I can not see the changes it should be doing in the dump... I'll try that AUTO_ETTR_DEBUG test now.
Title: Re: Auto ETTR on EOSM
Post by: a1ex on March 04, 2014, 10:43:47 PM
You don't see the changes because the module code runs before hdr video, and these things are reset by Canon code for each frame.

ETTR code actually assumes the exposure variables are reset by Canon code each time.
Title: Re: Auto ETTR on EOSM
Post by: Morghus on March 04, 2014, 11:17:39 PM
I tried that AUTO_ETTR_DEBUG block and I assume those blue dots should be on the diagonal red line? They are all horizontal and when the scene changes they go up and down.

I also tried setting ISO and shutter in each call now, no effect. Just for clarificaion, the Advanced Bracketing/Movie HDR code runs after the vsync hook has been called? What is done in between? It seems to work for those two things and those are not modules with vsync hooks.
Title: Re: Auto ETTR on EOSM
Post by: a1ex on March 05, 2014, 09:23:43 AM
Yes, the dots should be on the diagonal red line.

Advanced bracketing is for photos (does not use vsync).

Between HDR video (hdr_step) and your vsync hook there may be... other vsync hooks from other modules. The module vsync code is actually called from hdr_step.
Title: Re: Auto ETTR on EOSM
Post by: Morghus on March 05, 2014, 11:48:24 AM
That is useful information, I didn't know what that line was doing in hdr_step() but I couldn't find any other references to that, so it makes sense that the module callback is called from in there.

I did a quick test in hdr_step(), changing the ISO and shutter timer in some intervals and it only works while recording h264. Movie mode and not recording, or photo mode => no dice.


Edit: I moved the same code to the ettr callback and it seems to work there too when recording... I'm not sure why it didn't work yesterday, must have been something I missed
Title: Re: Auto ETTR on EOSM
Post by: a1ex on March 05, 2014, 12:39:14 PM
You could try playing with the state object hooks; it's mostly trial and error. This vsync hook runs in Canon's LiveView task (EVF), which is this one: http://a1ex.bitbucket.io/ML/states/EOSM-alt/sm28.htm

I suggest trying all the inputs from state 5 that do not change the state.

Another possibility is to rewrite the backend in order to override shutter via ADTG. This one should be a little more portable but we need to find a hook point for it first (on 5D3 I found something in DebugMsg, but it's not exactly portable and was not designed as a replacement for FRAME_SHUTTER_TIMER, so it may need some major rewrite).
Title: Re: Auto ETTR on EOSM
Post by: Morghus on March 05, 2014, 08:12:42 PM
I tried setting the ISO in all inputs of state 5, no dice... it works when starting to record a movie, but outside of that it doesn't. At least I think I tried it. As far as I know this code should do that:

state-object.c:
   
...
#ifdef EVF_STATE

    if (self == EVF_STATE && old_state == 5)
    {
    int iso = vsync_counter % 2 ? 72 : 96;
    set_frame_iso(iso);
    NotifyBox(1000, "%d", iso);
    }

...


Title: Re: Auto ETTR on EOSM
Post by: a1ex on March 05, 2014, 08:18:52 PM
What about:


if (self == EVF_STATE)
    {
    int iso = rand() % 2 ? 72 : 96;
    set_frame_iso(iso);
    //NotifyBox(1000, "%d", iso); /* don't enable this one, since it may slow down liveview */
    }


If that one works, all it's left is to narrow down the state/transition pair.
Title: Re: Auto ETTR on EOSM
Post by: Morghus on March 05, 2014, 08:25:29 PM
Nope, same behavior, no flickering until I start recording a movie, and flickering stops when recording stops :( If my understanding is right, the evfSetParamInterrupt input is called/spied on when LV is ready to accept new exposure params in the memory addresses?
Title: Re: Auto ETTR on EOSM
Post by: a1ex on March 05, 2014, 08:38:38 PM
Yap.

In this case... I'm afraid the only solution is to do this via ADTG. Will push a workaround meanwhile so it falls back to the slow method.

Let me know if this works: https://bitbucket.org/hudson/magic-lantern/commits/a6ff18c6aa44
Title: Re: Auto ETTR on EOSM
Post by: Morghus on March 05, 2014, 08:58:06 PM
It works for Always ON and HalfS DblClick, Auto Snap and using ETTR with the intervalometer doesn't seem to work, maybe something goes wrong while analyzing the image in image review? (I set it to 2 sec) Also, the Press SET trigger doesn't work since the M has a combined Q/SET button, maybe we can remove this entry for the M.
Title: Re: Auto ETTR on EOSM
Post by: a1ex on March 05, 2014, 09:02:03 PM
Probably it's worth checking button codes; do you get a BGMT_PRESS_SET event in LiveView?

If half-shutter trigger is working, I guess the preconditions are all OK, so... the only thing left is the button code, no?
Title: Re: Auto ETTR on EOSM
Post by: 1% on March 05, 2014, 09:32:12 PM
Photo mode and not recording H264 are actually the same as 60P just cut down to 30 fps. I could have sworn that the shutter fine tuning worked at rest though.
Title: Re: Auto ETTR on EOSM
Post by: Morghus on March 05, 2014, 09:33:17 PM
in auto_ettr_keypress_cbr
if (!display_idle()) return 1;
causes it to stop handling the event when Q/SET is pressed, even though the event gets there correctly with the right codes... this is because when you press that button, the Q menu comes up
if (key == MODULE_KEY_PRESS_SET) {
    NotifyBox(100, "SET PRESSED %d %d %d", AUTO_ETTR_TRIGGER_BY_SET, key == MODULE_KEY_PRESS_SET, key);
}

works before the display_idle check, not after
Title: Re: Auto ETTR on EOSM
Post by: a1ex on March 05, 2014, 09:39:22 PM
This means the Q menu already came up before the SET event (so it must be some other event).

Can you find that event and try to block it? (that is, return 0 when you receive that event)
Title: Re: Auto ETTR on EOSM
Post by: 1% on March 05, 2014, 09:55:20 PM
same behavior both ways, on to something
Title: Re: Auto ETTR on EOSM
Post by: Morghus on March 05, 2014, 11:11:41 PM
Alright that took a while... Since gui.h contains this
#define BGMT_Q TOUCH_1_FINGER
and key codes are mapped to different values in module.c (and unknown ones mapped to 0) I couldn't access the key code in the module. By outputting the pressed raw keycodes in module.c I was able to find out that blocking 0x1d in handle_module_keys prevents the quick menu from being opened, but that also blocks the BGMT_PRESS_SET event for some reason. However, it does not block the BGMT_UNPRESS_SET event so listening for that to start ETTR I could get it to work by also translating the 0x1d key code to a module code. While ETTR is enabled and set to Press SET, the quick menu becomes inaccessible though... would that be preferable to not being able to use SET as a trigger? I can clean up the code and submit a pull request if yes.
Title: Re: Auto ETTR on EOSM
Post by: 1% on March 06, 2014, 12:59:08 AM
does ETTR + intervalometer work after the fix? I'm only able to use it in TV/AV not M... it just never adjusts in the QR
Title: Re: Auto ETTR on EOSM
Post by: Morghus on March 06, 2014, 03:49:06 AM
No it doesn't work there yet, something doesn't work after analyzing the photo in image review, it should work in manual always on or with halfs dblclick
Title: Re: Auto ETTR on EOSM
Post by: a1ex on March 06, 2014, 07:19:11 AM
In "always on", whatever it does in QR will be canceled as soon as you get back to LiveView.

This probably needs re-thought for EOS-M; on other cameras, this mode is meant to be used outside LiveView.
Title: Re: Auto ETTR on EOSM
Post by: Morghus on March 06, 2014, 08:24:52 AM
So a CONFIG_IS_MIRRORLESS or CONFIG_EVF_ONLY or something should be introduced and then disable the parts where it tries to change things outside LV? I figure the EOS M and M2 won't be the last mirrorless cameras from canon and other ones probably should behave like the M.

Also:
Quote from: Morghus on March 05, 2014, 11:11:41 PM
While ETTR is enabled and set to Press SET, the quick menu becomes inaccessible though... would that be preferable to not being able to use SET as a trigger? I can clean up the code and submit a pull request if yes.
Where would be the right place to discuss this?
Title: Re: Auto ETTR on EOSM
Post by: a1ex on March 06, 2014, 08:33:22 AM
Yes, sounds good. You will need to export it to modules as a function though (since camera-specific ifdef's won't end up in module code).

I'm not sure what to suggest about SET (without trying, it's hard to evaluate how it feels like, and I don't know how essential is the Q menu on the M). Maybe sketching up some UI scenarios or maybe a mockup could be useful.

Another button... I guess it's unlikely to find one. Gestures would be probably cool, but not sure how practical (not to mention the implementation). An icon where you could tap? no idea, never tried a touch-screen camera.
Title: Re: Auto ETTR on EOSM
Post by: Morghus on March 07, 2014, 01:08:10 AM
Made a pull request, double tapping the screen will trigger ETTR.

I also found out why ETTR in combination with the intervalometer doesn't work: in auto_ettr_step() the following line fails:

    if (lens_info.raw_shutter == 0 && is_m) return;

raw_shutter seems to be 0, right before taking a photo it is set correctly, something seems to set it to 0 while or after taking a photo... I tried commenting out that line and it seems to fix it but I think corrections aren't always dead on, it takes one or two photos to settle fully.
Title: Re: Auto ETTR on EOSM
Post by: a1ex on March 07, 2014, 07:42:14 AM
Will check it, thanks.

In M mode, auto_ettr_work_m starts with tv = lens_info.raw_shutter. If that one is not valid (does not contain your current shutter speed), the math will be broken. Normally, on other cameras, it happens while flash is recharging, but not in QR. Maybe you can have a loop that prints this value to see whether we may need to wait or something?

So... were you able to turn off LiveView on the M? I've asked somewhere else and IIRC it wasn't possible.
Title: Re: Auto ETTR on EOSM
Post by: Morghus on March 07, 2014, 10:06:08 PM
Quote from: a1ex on March 07, 2014, 07:42:14 AM
So... were you able to turn off LiveView on the M? I've asked somewhere else and IIRC it wasn't possible.
NotifyBox(1000, "%d %d ", lv, raw_lv_is_enabled());

Pressing INFO cycles through these modes:

I'll test lens_info.raw_shutter next!
Title: Re: Auto ETTR on EOSM
Post by: a1ex on March 07, 2014, 10:08:23 PM
Yap. Can you take pictures from that screen with photo settings without going back to LiveView?

(this is what ETTR expects in Always On / Auto Snap settings outside LiveView)
Title: Re: Auto ETTR on EOSM
Post by: Morghus on March 07, 2014, 10:10:10 PM
No, unfortunately as soon as you press half shutter it goes back to LV
Title: Re: Auto ETTR on EOSM
Post by: Morghus on March 07, 2014, 10:52:29 PM
I tried a few things:

I don't know if I should create a background task in ettr that always runs, like the vsync_cbr, checking for the right conditions... would be a waste of resources. I don't know if there are any background tasks that I could use for that, any suggestions?
Title: Re: Auto ETTR on EOSM
Post by: a1ex on March 07, 2014, 10:59:57 PM
What about something like this?


diff -r 811c68f776a5 modules/ettr/ettr.c
--- a/modules/ettr/ettr.c Thu Mar 06 22:29:09 2014 +0200
+++ b/modules/ettr/ettr.c Fri Mar 07 23:57:52 2014 +0200
@@ -620,6 +620,16 @@

static int auto_ettr_work(int corr)
{
+    if (it's going to call auto_ettr_work_m)
+    {
+        /* in M mode, wait until shutter speed is reported by Canon firmware */
+        while (lens_info.raw_shutter == 0)
+        {
+            msleep(50);
+            /* add some timeout handling, e.g. 1-2 seconds */
+        }
+    }
+
     /* save initial exposure settings so we can print them */
     char* expo_settings = get_current_exposure_settings();
     snprintf(prev_exposure_settings, sizeof(prev_exposure_settings), "%s", expo_settings);
@@ -699,7 +709,6 @@
     if (shooting_mode != SHOOTMODE_M && shooting_mode != SHOOTMODE_AV && shooting_mode != SHOOTMODE_TV && shooting_mode != SHOOTMODE_P && shooting_mode != SHOOTMODE_MOVIE) return;
     int is_m = (shooting_mode == SHOOTMODE_M || shooting_mode == SHOOTMODE_MOVIE);
     if (lens_info.raw_iso == 0 && is_m) return;
-    if (lens_info.raw_shutter == 0 && is_m) return;
     if (auto_ettr_running) return;
     if (is_hdr_bracketing_enabled() && !AUTO_ETTR_TRIGGER_BY_SET) return;


Basically, I've moved that check in the background task created from the prop handler; there you don't have any restrictions regarding waiting, and there should be no side effects for the other cameras.
Title: Re: Auto ETTR on EOSM
Post by: 1% on March 07, 2014, 11:00:57 PM
why is it instant in av/tv?
Title: Re: Auto ETTR on EOSM
Post by: a1ex on March 07, 2014, 11:02:57 PM
In av/tv it only has to adjust exposure compensation; in M it decides shutter and ISO.

Imagine how it would look if it would also decide aperture.
Title: Re: Auto ETTR on EOSM
Post by: Morghus on March 07, 2014, 11:21:14 PM
Works perfectly now! I added a timeout and a status, how does this look?

diff -r 811c68f776a5 modules/ettr/ettr.c
--- a/modules/ettr/ettr.c Thu Mar 06 22:29:09 2014 +0200
+++ b/modules/ettr/ettr.c Fri Mar 07 23:19:25 2014 +0100
@@ -40,6 +40,7 @@
#define AUTO_ETTR_TRIGGER_BY_HALFSHUTTER_DBLCLICK (auto_ettr_trigger == 3)

/* status codes */
+#define ETTR_EXPO_PRECOND_TIMEOUT -2
#define ETTR_EXPO_LIMITS_REACHED -1
#define ETTR_NEED_MORE_SHOTS 0
#define ETTR_SETTLED 1
@@ -620,6 +621,21 @@

static int auto_ettr_work(int corr)
{
+    if (shooting_mode == SHOOTMODE_M || shooting_mode == SHOOTMODE_MOVIE)
+    {
+        /* in M mode, wait until shutter speed is reported by Canon firmware */
+        int waited = 0;
+        while (lens_info.raw_shutter == 0)
+        {
+            if (waited > 2000)
+            {
+                return ETTR_EXPO_PRECOND_TIMEOUT;
+            }
+            msleep(50);
+            waited += 50;
+        }
+    }
+
     /* save initial exposure settings so we can print them */
     char* expo_settings = get_current_exposure_settings();
     snprintf(prev_exposure_settings, sizeof(prev_exposure_settings), "%s", expo_settings);
@@ -671,6 +687,13 @@
         msleep(1000);
         bmp_printf(FONT_MED, 0, os.y0, "ETTR: expo limits reached\n%s", get_current_exposure_settings());
     }
+    else if (status == ETTR_EXPO_PRECOND_TIMEOUT)
+    {
+        beep_times(3);
+        ettr_pics_took = 0;
+        msleep(1000);
+        bmp_printf(FONT_MED, 0, os.y0, "ETTR: timeout while waiting for preconditions\n");
+    }
     else if (AUTO_ETTR_TRIGGER_AUTO_SNAP)
     {
         /* take another pic */
@@ -699,7 +722,6 @@
     if (shooting_mode != SHOOTMODE_M && shooting_mode != SHOOTMODE_AV && shooting_mode != SHOOTMODE_TV && shooting_mode != SHOOTMODE_P && shooting_mode != SHOOTMODE_MOVIE) return;
     int is_m = (shooting_mode == SHOOTMODE_M || shooting_mode == SHOOTMODE_MOVIE);
     if (lens_info.raw_iso == 0 && is_m) return;
-    if (lens_info.raw_shutter == 0 && is_m) return;
     if (auto_ettr_running) return;
     if (is_hdr_bracketing_enabled() && !AUTO_ETTR_TRIGGER_BY_SET) return;
Title: Re: Auto ETTR on EOSM
Post by: Morghus on March 08, 2014, 12:16:27 AM
Created a pull request to discuss this change: https://bitbucket.org/hudson/magic-lantern/pull-request/430/ettr-wait-for-preconditions-in-ettr-work
Title: Re: Auto ETTR on EOSM
Post by: a1ex on March 08, 2014, 07:49:14 AM
Great! Will try to polish them and merge later today or tomorrow, along with a few others in the queue that I have yet to try myself.