ISO Flash Effect - fast taking two pictures with parameters change

Started by Kouglov, April 18, 2018, 11:20:32 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Kouglov

Hello, I am a new member of the forum, I hope I post in the right category.

I would like to discuss an idea I had last night when thinking about a comon use of Flash in photography.

(Also, I'm french, so excuse my English level, I may not have always the specific right word for each case)

I really like long exposures shot where the photographer choose to "fix" a subject with a flash, like you make a 20 or 30 sec pose at 100 or 200 ISO, and in the middle, or at the end, *puff* you fire a flash, and your subject appears clearly on the image.

What I have in mind is doing the same only with ISO manipulation.

And that's why I want to discuss it here. I have been using ML for many months now, but I've just started to look into the code and coding my own modules.

So, I wanted to know if people had already experimented this ?

Is it possible to start a long expose shot for 30" at 100 ISO, and then, in the last 1 second of the shot, taking up the ISO to 1600 for example ?

I have identified this call function : lens_set_iso(iso);

But I still have to learn how modules are done, and of course, how ML manage tasks and how to shot a picture with it.

So the algorithm would be something like this :

[Init Module (with secondary ISO value selected from a menu)] --> [Calculate the time needed to correct exposure with the secondary ISO value]

then :

[Launch Task : shot the image (with current manual settings, like ISO 100, 30")]

and in parallel on another DryOS task with the same priority :

[Launch Timer calculated at init] --> [When the timer stops, change the ISO value with  lens_set_iso ]

I think it would be a very interessant feature in ML.
Please let me know if I've done something wrong, as it is the first time I post (except for my presentation)
6D

a1ex

You can do that with 2 different captures; the best place to experiment with is probably the silent picture module. You should be able to approximate it using ISO bracketing, although the delay between the two captures might be significant.

You will probably want to merge the two exposures in a single picture; if you have a DIGIC 5 model, you can do that in the camera.

Changing ISO during image capture is something I didn't experiment with; start here for some background info, or here to get a detailed log of what the camera is doing (during photo capture or anything else). You can also use the pre-built startup-log or startup-log-mpu builds to capture logs.




Just logged a 30-second exposure at ISO 400 on 5D3 1.1.3. Most important events:

23.882.713  ShootCaptu:ff14b8ac:93:03: scsReleaseOn
23.883.058  ShootCaptu:ff147854:93:03: scsReleaseStart
23.911.902  ShootCaptu:000117a0:91:01: [REG] ############ Start CMOS
23.911.926  ShootCaptu:00011844:91:01: [REG] CMOS:[0x0003]
23.911.946  ShootCaptu:00011844:91:01: [REG] CMOS:[0x1800]
23.911.964  ShootCaptu:00011844:91:01: [REG] CMOS:[0x2008]
23.911.980  ShootCaptu:00011844:91:01: [REG] CMOS:[0x3947]
23.911.997  ShootCaptu:00011844:91:01: [REG] CMOS:[0x4718]
23.912.013  ShootCaptu:00011844:91:01: [REG] CMOS:[0x5c05]
23.912.029  ShootCaptu:00011844:91:01: [REG] CMOS:[0x60b0]
23.912.046  ShootCaptu:00011844:91:01: [REG] CMOS:[0x7800]
23.912.058  ShootCaptu:000042b0:91:01: [REG] CMOS:[3010] <----- Excel Tab Number
23.912.180  ShootCaptu:ff14827c:93:03: scsReleaseData
23.920.867  ShootCaptu:ff148aa8:93:03: NormalCapture(scsReleaseData)
23.929.984  ShootCaptu:ff14b6f4:93:03: scsProperty ID=0x80030012(0x16)
23.941.052  ShootCaptu:ff149634:93:03: scsPreCapReadyReadoutDone
23.941.101  ShootCaptu:ff2126fc:92:02: SetHeadForReset
23.941.336  ShootCaptu:000117a0:91:01: [REG] ############ Start CMOS
23.941.355  ShootCaptu:00011844:91:01: [REG] CMOS:[0x3947]
23.941.367  ShootCaptu:00005128:91:01: [REG] CMOS:[0310] <----- Excel Tab Number
23.984.324  ShootCaptu:ff149874:93:03: scsCapReady
23.984.346  ShootCaptu:ff1498f4:93:03: scsCapReady
24.116.608  ShootCaptu:ff14a7dc:93:03: scsVdInterrupt
24.360.743  ShootCaptu:ff14a7dc:93:03: scsVdInterrupt
... (many scsVdInterrupt events ommitted) ...
55.361.521  ShootCaptu:ff14a7dc:93:03: scsVdInterrupt
55.605.623  ShootCaptu:ff14a7dc:93:03: scsVdInterrupt
55.849.728  ShootCaptu:ff14a7dc:93:03: scsVdInterrupt
55.931.359  ShootCaptu:ff14a70c:93:03: scsReleaseEnd
55.931.432  ShootCaptu:ff14b8ec:93:03: scsReleaseOff
56.093.833  ShootCaptu:ff14a7dc:93:03: scsVdInterrupt
56.323.224  ShootCaptu:ff149874:93:03: scsCapReady
56.323.249  ShootCaptu:ff1498f4:93:03: scsCapReady
56.325.620  ShootCaptu:000117a0:91:01: [REG] ############ Start CMOS
56.325.639  ShootCaptu:00011844:91:01: [REG] CMOS:[0x0223]
56.325.656  ShootCaptu:00011844:91:01: [REG] CMOS:[0x1800]
56.325.672  ShootCaptu:00011844:91:01: [REG] CMOS:[0x2008]
56.325.688  ShootCaptu:00011844:91:01: [REG] CMOS:[0x3944]
56.325.701  ShootCaptu:00004990:91:01: [REG] CMOS:[3022] <----- Excel Tab Number
56.325.709  ShootCaptu:000117a0:91:01: [REG] ############ Start CMOS
56.325.726  ShootCaptu:00011844:91:01: [REG] CMOS:[0x5c05]
56.325.737  ShootCaptu:000049a0:91:01: [REG] CMOS:[0307] <----- Excel Tab Number
56.325.758  ShootCaptu:ff212eb8:92:02: SetHeadForReadout
56.337.916  ShootCaptu:ff149c50:93:03: scsCapEnd
56.338.156  ShootCaptu:ff212ed8:92:02: SetHeadForStandby
56.340.409    EventMgr:ff0da6cc:93:03: scsAFPINTParamCBR(JobID=87775)
56.341.086    EventMgr:ff0da638:93:03: scsIMAGEParamCBR(JobID=87775)
56.341.590    EventMgr:ff0dabd8:93:03: scsAfterReleaseDataCBR(87775)
56.468.530  ShootCaptu:ff149d60:93:03: scsFinalReadoutDone
56.469.323  ShootCaptu:ff2126fc:92:02: SetHeadForReset
56.476.160  ShootCaptu:ff14a154:93:03: scsFinalReadoutDone (2057)
56.687.580  ShootCaptu:ff14b6f4:93:03: scsProperty ID=0x80030012(0x14)
56.907.896  ShootCaptu:ff14b6f4:93:03: scsProperty ID=0x80030012(0x10)
56.908.009  ShootCaptu:ff14b694:93:03: scsDevDone[1]
57.934.801  ShootCaptu:ff14b6f4:93:03: scsProperty ID=0x80030012(0x0)
57.934.917  ShootCaptu:ff14b694:93:03: scsDevDone[0]


The interesting part is that analog ISO (configured with CMOS[0], e.g. CMOS:[0x0223] == ISO 400, see e.g. dual_iso.pdf) is applied at the very end, right before readout; that means, ISO doesn't seem to be used during image capture, but only for readout. At the beginning of the image capture, this register is set to ISO 100 for some dummy capture (whatever that's used for; probably calibration).

Kouglov

Thanks for your very fast anwser !

I wasn't thinking of the silent picture module, good point ! I will read the entire code.

As for the delay, I was planning on taking pictures of racing cars at night with this effect. My goal is to have the "path" produced by the lights, and the car "fixed" on the image. (even if it's blurry, that's not a problem)

Perhaps this delay will not be significant if I don't read and save the image buffer between the two captures (if the buffer is big enough to contain both images).

I see a lot of references to the MLV_REC module, wich I may disable in my experiments in the first time.
I see also a "Take pictures until memory gets full, then save to card" wich anwser my question on taking both images, and saving them after.

For a first proof of concept, I may not embed image merging in my module, as I would be able to stack them in photoshop after.
As for the merge of the 2 images, I have a 6D mark I, wich have a DIGIC 5+, so this is clearly a solution if I continue this project after the PoC

so, things may looks like this :

silent_pic_take_fullres(1); //(with camera manual parameters)
//as soon as this shot is complete, launch another one with higher ISO value and the adequate expo time
lens_set_iso(iso);
silent_pic_take_fullres(1);


Is there a way I can delay the "save the raw image as DNG or MLV" part of the silent_take function without loosing pointers to the buffer ?

EDIT :

So, as ISO doesn't seem to be used during image capture, could we imagine doing a first readout at ISO 100, and another one at ISO 1600 for example ?
I may not still understand how the events works in detail, but I see a limitation here : there is no time indication when doing the readout, all the data will already be here, reading it at ISO 100 or 1600 will end up just having the same data filtered ?


EDIT 2 :

Okay so I looked at the example. Maybe I can find a solution with something like :


call("FA_CaptureTestImage", job);
//We capture the first image with manual parameters, for example 10", 200 ISO
//Forget the imageReview for the moment
copy_first = (void*) call("FA_CreateTestImage");
copy_buf1 = (void*) call("FA_GetCrawBuf", copy_first);
//I create a first buffer wich will be used to save the first image

lens_set_iso(isoless_recovery_iso); //Setting up new ISO value
//Dumb calculation here, mathematician trigger warning :
int shutter = lens_format_shutter(1/isoless_recovery_iso) ; //SHUTTER_1_4000
bmp_printf(FONT_MED, 0, 0, "Shutter chosen : %d", shutter);
lens_set_rawshutter(shutter); //Setting the previously calculated shutter time (wich would be short)


call("FA_CaptureTestImage", job);
copy_second = (void*) call("FA_CreateTestImage");
copy_buf2 = (void*) call("FA_GetCrawBuf", copy_second);

//And finishing by doing the two image saving with memcpy the buffer and silent_pic_save_file


Does my int shutter = lens_format_shutter(1/isoless_recovery_iso) would work ?
I've not found any informations on the units used in this function  :'(

What I fear the most is bricking my camera :(

6D

Kouglov

EDIT : I found the issue, wrong filename size (exceed 8 character)
Now it works.

What I have for now : dual DNG shot in liveView, with iso and shutter changed, but the result seems to be two times the same image.
This code crash the camera some times.
There seems to be buffer rewriting, how can I save the first image buffer during the second shot ?
Also, sometimes, I record only 33kb files, I don't know why.

My edited code from the silent module :


/** Silent pictures **/

#include <module.h>
#include <dryos.h>
#include <bmp.h>
#include <menu.h>
#include <config.h>
#include <property.h>
#include <raw.h>
#include <shoot.h>
#include <zebra.h>
#include <beep.h>
#include <lens.h>
#include <focus.h>
#include <string.h>
#include <battery.h>
#include <powersave.h>

#include "../lv_rec/lv_rec.h"
#include "../mlv_rec/mlv.h"

static uint64_t ret_0_long() { return 0; }

extern WEAK_FUNC(ret_0) void display_filter_get_buffers(uint32_t** src_buf, uint32_t** dst_buf);

extern WEAK_FUNC(ret_0) void mlv_fill_rtci(mlv_rtci_hdr_t *hdr, uint64_t start_timestamp);
extern WEAK_FUNC(ret_0) void mlv_fill_expo(mlv_expo_hdr_t *hdr, uint64_t start_timestamp);
extern WEAK_FUNC(ret_0) void mlv_fill_lens(mlv_lens_hdr_t *hdr, uint64_t start_timestamp);
extern WEAK_FUNC(ret_0) void mlv_fill_idnt(mlv_idnt_hdr_t *hdr, uint64_t start_timestamp);
extern WEAK_FUNC(ret_0) void mlv_fill_wbal(mlv_wbal_hdr_t *hdr, uint64_t start_timestamp);
extern WEAK_FUNC(ret_0) void mlv_fill_styl(mlv_styl_hdr_t *hdr, uint64_t start_timestamp);
extern WEAK_FUNC(ret_0_long) uint64_t mlv_generate_guid();
extern WEAK_FUNC(ret_0) void mlv_init_fileheader(mlv_file_hdr_t *hdr);
extern WEAK_FUNC(ret_0) void mlv_set_type(mlv_hdr_t *hdr, char *type);
extern WEAK_FUNC(ret_0_long) uint64_t mlv_set_timestamp(mlv_hdr_t *hdr, uint64_t start);

extern WEAK_FUNC(ret_0) int GetBatteryLevel();
extern WEAK_FUNC(ret_0) int GetBatteryTimeRemaining();
extern WEAK_FUNC(ret_0) int GetBatteryDrainRate();


//~ #define FEATURE_SILENT_PIC_RAW

static CONFIG_INT( "silent.pic.iso", silent_pic_recovery_iso, 0);
static CONFIG_INT( "silent.pic.shutter", silent_pic_recovery_shutter, 0);
static CONFIG_INT( "silent.pic", silent_pic_enabled, 0 );
static CONFIG_INT( "silent.pic.mode", silent_pic_mode, 5 );
static CONFIG_INT( "silent.pic.slitscan.mode", silent_pic_slitscan_mode, 0 );
static CONFIG_INT( "silent.pic.file_format", silent_pic_file_format, 0 );
#define SILENT_PIC_MODE_SIMPLE 0
#define SILENT_PIC_MODE_BURST 1
#define SILENT_PIC_MODE_BURST_END_TRIGGER 2
#define SILENT_PIC_MODE_BEST_FOCUS 3
#define SILENT_PIC_MODE_SLITSCAN 4
#define SILENT_PIC_MODE_FULLRES 5

#define SILENT_PIC_FILE_FORMAT_DNG 0
#define SILENT_PIC_FILE_FORMAT_MLV 1

#define SILENT_PIC_MODE_SLITSCAN_SCAN_TTB 0 // top to bottom
#define SILENT_PIC_MODE_SLITSCAN_SCAN_BTT 1 // bottom to top
#define SILENT_PIC_MODE_SLITSCAN_SCAN_LTR 2 // left to right
#define SILENT_PIC_MODE_SLITSCAN_SCAN_RTL 3 // right to left
#define SILENT_PIC_MODE_SLITSCAN_CENTER_H 4 // center horizontal
//#define SILENT_PIC_MODE_SLITSCAN_CENTER_V 5 // center vertical

//static int silent_pic_mlv_available = 0;
//static mlv_file_hdr_t mlv_file_hdr;
//static uint64_t mlv_start_timestamp = 0;
static char image_file_name[100];
//static uint32_t mlv_max_filesize = 0xFFFFFFFF;
static int mlv_file_frame_number = 0;

static int long_exposure_fix_enabled = 0;

/* forward reference */
static struct menu_entry silent_menu[];

static int iso_original = 0;
static int shutter_original = 0;

static int new_iso = 0;
static int new_shutter = 0;

static MENU_UPDATE_FUNC(silent_pic_mode_update)
{
    /* reveal options for the current shooting mode, if any */
   // silent_menu[0].children[1].shidden =(silent_pic_mode != SILENT_PIC_MODE_SLITSCAN);
}


static MENU_UPDATE_FUNC(isocheck)
{

switch (silent_pic_recovery_iso)
    {
        case -12:
            new_iso = ISO_100;
            break;
        case -11:
            new_iso = ISO_125;
            break;
        case -10:
            new_iso = ISO_160;
            break;
        case -9:
            new_iso = ISO_200;
            break;
        case -8:
            new_iso = ISO_250;
            break;
        case -7:
            new_iso = ISO_320;
            break;
        case -6:
            new_iso = ISO_400;
            break;
        case -5:
            new_iso = ISO_500;
            break;
        case -4:
            new_iso = ISO_640;
            break;
        case -3:
            new_iso = ISO_800;
            break;
        case -2:
            new_iso = ISO_1000;
            break;
        case -1:
            new_iso = ISO_1250;
            break;
        case 0:
            new_iso = ISO_1600;
            break;
        case 1:
            new_iso = ISO_2000;
            break;
        case 2:
            new_iso = ISO_2500;
            break;
        case 3:
            new_iso = ISO_3200;
            break;
        case 4:
            new_iso = ISO_4000;
            break;
       

    }
//bmp_printf(FONT_MED, 0, 0, "Iso debug : %d", silent_pic_recovery_iso);
    bmp_printf(FONT_MED, 0, 0, "Iso chosen : %d", new_iso);

}


static MENU_UPDATE_FUNC(shuttercheck)
{

switch (silent_pic_recovery_shutter)
    {
        case -12:
            new_shutter = SHUTTER_1_60;
            break;
        case -11:
            new_shutter = SHUTTER_1_80;
            break;
        case -10:
            new_shutter = SHUTTER_1_90;
            break;
        case -9:
            new_shutter = SHUTTER_1_100;
            break;
        case -8:
            new_shutter = SHUTTER_1_125;
            break;
        case -7:
            new_shutter = SHUTTER_1_160;
            break;
        case -6:
            new_shutter = SHUTTER_1_180;
            break;
        case -5:
            new_shutter = SHUTTER_1_200;
            break;
        case -4:
            new_shutter = SHUTTER_1_250;
            break;
        case -3:
            new_shutter = SHUTTER_1_320;
            break;
        case -2:
            new_shutter = SHUTTER_1_350;
            break;
        case -1:
            new_shutter = SHUTTER_1_400;
            break;
        case 0:
            new_shutter = SHUTTER_1_500;
            break;
        case 1:
            new_shutter = SHUTTER_1_640;
            break;
        case 2:
            new_shutter = SHUTTER_1_750;
            break;
        case 3:
            new_shutter = SHUTTER_1_800;
            break;
        case 4:
            new_shutter = SHUTTER_1_1000;
            break;
        case 5:
            new_shutter = SHUTTER_1_1250;
            break;
        case 6:
            new_shutter = SHUTTER_1_1500;
            break;
        case 7:
            new_shutter = SHUTTER_1_1600;
            break;
        case 8:
            new_shutter = SHUTTER_1_2000;
            break;
        case 9:
            new_shutter = SHUTTER_1_2500;
            break;
        case 10:
            new_shutter = SHUTTER_1_3000;
            break;
        case 11:
            new_shutter = SHUTTER_1_3200;
            break;
        case 12:
            new_shutter = SHUTTER_1_4000;
            break;
       

    }
//bmp_printf(FONT_MED, 0, 0, "Shutter debug : %d", silent_pic_recovery_shutter);
    bmp_printf(FONT_MED, 0, 0, "Shutter chosen : %d", new_shutter);

}

static MENU_UPDATE_FUNC(silent_pic_display)
{
    /* reset the MLV frame counter if we enter ML menu */
    /* exception: don't reset if the intervalometer is running - we might want to change some settings on the fly */
    if (!is_intervalometer_running())
    {
        mlv_file_frame_number = 0;
    }
   
    if (!silent_pic_enabled)
        return;


     //MENU_SET_VALUE("Full-res");

   
     //MENU_SET_HELP("File format: 14-bit DNG, individual files.");
     //MENU_APPEND_VALUE(", DNG");

   
    if (silent_pic_mode == SILENT_PIC_MODE_FULLRES && (shooting_mode != SHOOTMODE_M || is_movie_mode()))
    {
        MENU_SET_WARNING(MENU_WARN_NOT_WORKING, "Full-res pictures only work in Manual (M) photo mode.");
    }
   
    //silent_pic_check_mlv(entry, info);
}

static char* silent_pic_get_name()
{
    char *extension;

    extension = "DNG";

   
    int file_number = get_shooting_card()->file_number;
   
    int is_mlv = (silent_pic_file_format == SILENT_PIC_FILE_FORMAT_MLV);
   
    if (is_intervalometer_running() && !is_mlv)
    {
        char pattern[100];
        snprintf(pattern, sizeof(pattern), "%s/%%08d.%s", get_dcim_dir(), 0, extension);
        get_numbered_file_name(pattern, 99999999, image_file_name, sizeof(image_file_name));
    }
    else
    {
        char pattern[100];
        snprintf(pattern, sizeof(pattern), "%s/%04d%%04d.%s", get_dcim_dir(), file_number, 0, extension);
        get_numbered_file_name(pattern, 9999, image_file_name, sizeof(image_file_name));
    }
    bmp_printf(FONT_MED, 0, 37, "%s    ", image_file_name);
    return image_file_name;
}

static int silent_pic_save_file(struct raw_info * raw_info, int capture_time_ms)
{

        char* filename = silent_pic_get_name();
        int ok = save_dng(filename, raw_info);
        if (!ok) bmp_printf( FONT_MED, 0, 83, "DNG save error (card full?)");
        return ok;

}

static void show_battery_status()
{
    if ((void*)&GetBatteryLevel == (void*)&ret_0)
    {
        return;
    }
   
    int l = GetBatteryLevel();
    int r = GetBatteryTimeRemaining();
    int d = GetBatteryDrainRate();
    bmp_printf(FONT_MED, 0, 480 - font_med.height,
        "Battery: %d%%, %dh%02dm, %d%%/h",
        l, 0,
        r / 3600, (r % 3600) / 60,
        d, 0
    );
}

/* FA test image code only looks at these 3 properties - doesn't know about auto ISO & stuff */
/* lens_info data may not be in sync, e.g. when using expo override */
/* so, check these props directly before taking a picture */
static PROP_INT(PROP_ISO, prop_iso);
static PROP_INT(PROP_SHUTTER, prop_shutter);

/* this will check (poll) if we are still in QR (or paused LV) mode, every 100ms,
* until preview_time expires or until you get out of QR, whichever happens first
* if we didn't leave QR mode, it will turn off the display
*/
static void display_off_if_qr_mode(int unused, int preview_time)
{
    if (is_play_or_qr_mode() || LV_PAUSED)
    {
        if (preview_time > 0)
        {
            /* OK for now, re-check after 100ms */
            delayed_call(100, display_off_if_qr_mode, (void*)(preview_time - 100));
        }
        else
        {
            /* preview_time expired */
            display_off();
        }
    }
}

static uint32_t SLOWEST_SHUTTER = SHUTTER_15s;

static void long_exposure_fix()
{
    unsigned shutter_old = lens_info.raw_shutter;
    if (long_exposure_fix_enabled && shutter_old < SHUTTER_0s8)
    {
        unsigned shutter = SHUTTER_1_500;
        prop_request_change_wait( PROP_SHUTTER, &shutter, 4, 100);
        void* job = (void*) call("FA_CreateTestImage");
        /* We need paused lv, otherwise the camera will freeze */
        if (!LV_PAUSED && gui_state != GUISTATE_QR)
        {
            gui_uilock(UILOCK_EVERYTHING);
            PauseLiveView();
        }
        call("FA_CaptureTestImage", job);
        call("FA_DeleteTestImage", job);
       
        prop_request_change_wait( PROP_SHUTTER, &shutter_old, 4, 100);
    }
}

static int
silent_pic_take_fullres(int interactive)
{
    int ok = 1;
   
    /* get out of LiveView, but leave the shutter open */
    PauseLiveView();
   
    /* block all keys until finished, to avoid errors */
    gui_uilock(UILOCK_EVERYTHING);

    clrscr();
    vram_clear_lv();
   
    char* error_msg = 0;

    if (shooting_mode != SHOOTMODE_M)
    {
        error_msg = "Manual (M) mode is required.";
        goto err;
    }

    if (prop_iso == 0 || prop_shutter == 0)
    {
        error_msg = "Manual exposure is required.";
        goto err;
    }

    /* there are problems with shutter speeds slower than 15 seconds */
    /* (corrupted image and camera lockup, at least on 5D2 and 550D) */
    if (prop_shutter < SLOWEST_SHUTTER)
    {
        static char expo_msg[50];
        snprintf(expo_msg, sizeof(expo_msg), "Exposure too long (max %s).", lens_format_shutter(SLOWEST_SHUTTER));
        error_msg = expo_msg;
        goto err;
    }
   
    if (!can_use_raw_overlays_photo())
    {
        error_msg = "Set picture quality to RAW.";
        goto err;
    }
   
    /* Canon photo taking code is busy? (may happen if you press the shutter fully) */
    while (lens_info.job_state)
    {
        bmp_printf(FONT_MED, 0, 0, "Busy...");
        msleep(10);
    }
   
    /* Are we still in paused LV mode? (QR is also allowed) */
    if (!LV_PAUSED && gui_state != GUISTATE_QR)
    {
        goto err;
    }
   
    display_off();

    /* we'll need these later */
    struct JobClass * copy_job = 0;
    void* copy_buf = 0;

    struct JobClass * copy_job2 = 0;
    void* copy_buf2 = 0;

    /* from now on, we can no longer jump to "err" */

    /*
     * This enters factory testing mode (SRM_ChangeMemoryManagementForFactory),
     * reads PROP_ISO, PROP_SHUTTER and PROP_APERTURE,
     * and creates a "job" object (CreateSkeltonJob)
     */
    struct JobClass * job = (void*) call("FA_CreateTestImage");
   
    lens_info.job_state = 1;
    info_led_on();
    int t0 = get_ms_clock_value();
   
    /*
     * This one sets PROP_FA_ADJUST_FLAG to 4 (configures scsReleaseData for DARK_MEM1),
     * then sends event 0 to SCS state (scsReleaseStart),
     * then sends event 1 to SCS state (scsReleaseData),
     * then resets PROP_FA_ADJUST_FLAG back to 0.
     *
     * The SCS state machine continues with scsDummyReadoutDone,
     * scsCapReady, scsCapEnd and scsFinalReadoutDone.
     *
     * After that, raw image data will be written by CCDWriteEDmacCompleteCBR
     * and available from RAW_PHOTO_EDMAC (defined in raw.c)
     */
    call("FA_CaptureTestImage", job);
   
    int t1 = get_ms_clock_value();
    int capture_time = t1 - t0;

    info_led_off();
    lens_info.job_state = 0;

    /* prepare to save the file */
    struct raw_info local_raw_info = raw_info;
    struct raw_info local_raw_info2 = raw_info;
   
    /* DNG only: make a copy of the image, because save_dng will overwrite the contents of the raw buffer */
    copy_job = (void*) call("FA_CreateTestImage");
    copy_buf = (void*) call("FA_GetCrawBuf", copy_job);


    if (!copy_buf)
    {
        bmp_printf(FONT_MED, 0, 0, "Memory error1");
        goto cleanup;
    }


    //call("FA_DeleteTestImage", job);
    //job = (void*) call("FA_CreateTestImage");

    //Shot 1 finished
   
    shutter_original = lens_info.raw_shutter;

    iso_original = lens_info.raw_iso;

    lens_set_rawiso(new_iso);
    lens_set_rawshutter(new_shutter);
    //Setting up new ISO value : silent_pic_recovery_iso
    //bmp_printf(FONT_MED, 0, 0, "Shutter chosen : %d", shutter);
   
    //Setting the previously calculated shutter time (wich would be short)



   
    //Starting second shot
    lens_info.job_state = 1;
    info_led_on();
    int t3 = get_ms_clock_value();
    call("FA_CaptureTestImage", job);
    int t2 = get_ms_clock_value();
    int capture_time2 = t3 - t2;
    info_led_off();
    lens_info.job_state = 0;
    //Ended shot
    local_raw_info = raw_info;
   
    /* DNG only: make a copy of the image, because save_dng will overwrite the contents of the raw buffer */
    copy_job2 = (void*) call("FA_CreateTestImage");
    copy_buf2 = (void*) call("FA_GetCrawBuf", copy_job2);

    if (!copy_buf2)
    {
        bmp_printf(FONT_MED, 0, 0, "Memory error2");
        goto cleanup;
    }

   

   
        /* even if we don't preview, we still have to update raw parameters */
        raw_set_dirty();
        /* fake a QR mode, so the raw backend knows what parameters to apply */
        /* but do not notify others (triggering the property would freeze on some cameras) */
        /* however this won't trigger ETTR & co (but you'll see a warning in the menu) */
        int old_gui_state = gui_state;
        gui_state = GUISTATE_QR;
        ok = raw_update_params();
        gui_state = old_gui_state;
        if (!ok)
        {
            display_on();
            msleep(100);
            bmp_printf(FONT_MED, 0, 0, "Raw error");
            goto cleanup;
        }
   

   
   
    /* save the raw image as DNG or MLV */
    int save_time;
   
    {
        bmp_printf(FONT_MED, 0, 60, "Saving %d x %d...", local_raw_info.jpeg.width, local_raw_info.jpeg.height);
        bmp_printf(FONT_MED, 0, 83, "Captured in %d ms.", capture_time);
       
        int t0 = get_ms_clock_value();
       
        if (copy_buf)
        {
            local_raw_info.buffer = copy_buf;
            memcpy(local_raw_info.buffer, raw_info.buffer, local_raw_info.frame_size);
        }
       
        ok = silent_pic_save_file(&local_raw_info, capture_time);
        //char* filename = silent_pic_get_name();
        //int ok = save_dng(filename, &local_raw_info);
        //if (!ok) bmp_printf( FONT_MED, 0, 83, "DNG1 save error (card full?)");
        int t1 = get_ms_clock_value();
        save_time = t1 - t0;
     
        if (ok)
        {
            bmp_printf(FONT_MED, 0, 60, "Saved %d x %d (%d ms, %d MiB/s).   ",
                local_raw_info.jpeg.width, local_raw_info.jpeg.height,
                save_time, (int)roundf(local_raw_info.frame_size * 1000.0f / (t1 - t0) / 1024.0f / 1024.0f)
            );
        }
    }
    //Savec Image 1

   {
        bmp_printf(FONT_MED, 0, 60, "Saving %d x %d...", local_raw_info.jpeg.width, local_raw_info.jpeg.height);
        bmp_printf(FONT_MED, 0, 83, "Captured in %d ms.", capture_time2);
       
        int t0 = get_ms_clock_value();
       
        if (copy_buf2)
        {
            local_raw_info.buffer = copy_buf2;
            memcpy(local_raw_info.buffer, raw_info.buffer, local_raw_info.frame_size);
        }
       
        ok = silent_pic_save_file(&local_raw_info, capture_time2);
        //char* filename = silent_pic_get_name();
        //int ok = save_dng(filename, &local_raw_info);
        //if (!ok) bmp_printf( FONT_MED, 0, 83, "DNG1 save error (card full?)");
        int t1 = get_ms_clock_value();
        save_time = t1 - t0;
     
        if (ok)
        {
            bmp_printf(FONT_MED, 0, 60, "Saved %d x %d (%d ms, %d MiB/s).   ",
                local_raw_info.jpeg.width, local_raw_info.jpeg.height,
                save_time, (int)roundf(local_raw_info.frame_size * 1000.0f / (t1 - t0) / 1024.0f / 1024.0f)
            );
        }
    }

    lens_set_rawiso(iso_original);
    lens_set_rawshutter(shutter_original);
   
        bmp_printf(FONT_MED, 0, 106, "Long half-shutter will take another picture.");
        int preview_delay = MAX(1000, image_review_time * 1000 - save_time);
        delayed_call(100, display_off_if_qr_mode, (void*)preview_delay);


cleanup:
    /*
     * This deallocates the job object (DeleteSkeltonJob),
     * and after the last job is deallocated, it gets out of factory mode
     * (SRM_ChangeMemoryManagementForImage)
     */
    call("FA_DeleteTestImage", job);
   
    if (copy_job)
    {
        call("FA_DeleteTestImage", copy_job);
    }

    if (copy_job2)
    {
        call("FA_DeleteTestImage", copy_job2);
    }
   
    long_exposure_fix();
    gui_uilock(UILOCK_NONE);
   
    return ok;

err:
    if (error_msg)
    {
        bmp_printf(FONT_MED, 0, 0, "%s", error_msg);
        msleep(2000);
    }
    gui_uilock(UILOCK_NONE);
    ResumeLiveView();
    return 0;
}

static unsigned int
silent_pic_take(unsigned int interactive) // for remote release, set interactive=0
{
    if (!silent_pic_enabled)
    {
        /* tell the photo taking backend that no custom picture was taken */
        /* (so it should try another custom picture handler or a regular picture) */
        return CBR_RET_CONTINUE;
    }
   
    int ok = 0;

    /* in fullres mode, go to LiveView only if in normal photo mode */
    /* if it's in QR or paused LV (most likely from previous silent picture), just stay there */
    if (!lv && !LV_PAUSED && gui_state != GUISTATE_QR) force_liveview();
    ok = silent_pic_take_fullres(interactive);


    /* reset the powersave timer */
    powersave_prolong();

    return ok ? CBR_RET_STOP : CBR_RET_ERROR;
}

static unsigned int silent_pic_polling_cbr(unsigned int ctx)
{
    if (!silent_pic_enabled)
        return 0;

    /* fullres silent pics only work in M mode,
     * and they may screw up things if triggered while recording. */
    if (silent_pic_mode == SILENT_PIC_MODE_FULLRES && (shooting_mode != SHOOTMODE_M || is_movie_mode()))
        return 0;

    static int silent_pic_countdown;
    if (!display_idle())
    {
        silent_pic_countdown = 10;
    }
    else if (!get_halfshutter_pressed())
    {
        if (silent_pic_countdown)
            silent_pic_countdown--;
    }

    if (lv && get_halfshutter_pressed())
    {
        /* half-shutter was pressed while in playback mode, for example */
        if (silent_pic_countdown)
        {
            /* in this case, require a long press to trigger a new picture */
            for (int i = 0; i < 10; i++)
            {
                msleep(50);
                if (!get_halfshutter_pressed())
                {
                    return 0;
                }
            }
        }

        if (lv && !is_manual_focus())
        {
            /* try to ignore the AF button, and only take pictures on plain half-shutter */
            /* problem: lv_focus_status is not updated right away :( */
            bmp_printf(FONT_MED, 0, 37, "Hold on...");
            for (int i = 0; i < 10; i++)
            {
                wait_lv_frames(1);
               
                if (lv_focus_status == 3)
                {
                    while (get_halfshutter_pressed())
                    {
                        bmp_printf(FONT_MED, 0, 37, "Focusing...");
                        msleep(10);
                    }
                    redraw();
                    return 0;
                }
            }
        }
       
        silent_pic_take(1);
    }
   
    if (LV_PAUSED && get_halfshutter_pressed())
    {
        /* long press will trigger a second picture */
        /* short press will go back to LiveView */
        info_led_on();
        for (int i = 0; i < 10; i++)
        {
            msleep(50);
            if (!get_halfshutter_pressed())
            {
                info_led_off();
                ResumeLiveView();
                return 0;
            }
        }
        info_led_off();
       
        silent_pic_take(1);
    }
   
    return 0;
}

static struct menu_entry silent_menu[] = {
    {
        .name = "ISO Flash",
        .priv = &silent_pic_enabled,
        .update = silent_pic_display,
        .max  = 1,
        .depends_on = DEP_LIVEVIEW | DEP_CFN_AF_BACK_BUTTON,
        .help  = "Take two pics in LiveView without moving the shutter mechanism. \n"
"One at manual chosen ISO, and one at higher selected ISO value",
        .submenu_width = 650,
        .children =  (struct menu_entry[]) {
            {
                .name = "Recovery ISO",
                .priv = &silent_pic_recovery_iso,
                .update = isocheck,
                .min = -12,
                .max = 4,
                //.unit = UNIT_ISO,
                .choices = CHOICES("100", "125","160","200","250","320","400","500","640","800","1000","1250","1600","2000","2500","3200","4000"),
                .help  = "ISO for second shot",
                //.help2 = "Test",
            },
    {
                .name = "Recovery Shutter",
                .priv = &silent_pic_recovery_shutter,
                .update = shuttercheck,
                .min = -12,
                .max = 12,
                //.unit = UNIT_ISO,
                .choices = CHOICES("60", "80", "90", "100", "125", "160", "180", "200", "250", "320", "350", "400", "500", "640", "750", "800", "1000", "1250", "1500", "1600", "2000", "2500", "3000", "3200", "4000"),
                .help  = "shutter for second shot",
                .help2 = "(Indicated in 1 / value)",
            },
            MENU_EOL,
        }
       
    }
};


static unsigned int silent_init()
{
    menu_add("Shoot", silent_menu, COUNT(silent_menu));
    /* fixme in core: prop handlers should trigger when initializing, but they do not */
    prop_iso = lens_info.raw_iso;
    prop_shutter = lens_info.raw_shutter;

    //silent_pic_mlv_available = (mlv_generate_guid() != 0ULL);

    if (is_camera("500D", "*") || is_camera("550D", "*") || is_camera("600D", "*"))
    {
        /* see http://www.magiclantern.fm/forum/index.php?topic=12523.msg129874#msg129874 */
        long_exposure_fix_enabled = 1;
    }

   
    return 0;
}

static unsigned int silent_deinit()
{
    return 0;
}

MODULE_INFO_START()
    MODULE_INIT(silent_init)
    MODULE_DEINIT(silent_deinit)
MODULE_INFO_END()

MODULE_CBRS_START()
    MODULE_CBR(CBR_CUSTOM_PICTURE_TAKING, silent_pic_take, 0)
    MODULE_CBR(CBR_SHOOT_TASK, silent_pic_polling_cbr, 0)
    //MODULE_CBR(CBR_VSYNC, silent_pic_raw_vsync, 0)
    //MODULE_CBR(CBR_DISPLAY_FILTER, silent_pic_preview, 0)
MODULE_CBRS_END()

MODULE_CONFIGS_START()
    MODULE_CONFIG(silent_pic_recovery_iso)
    MODULE_CONFIG(silent_pic_recovery_shutter)
    MODULE_CONFIG(silent_pic_enabled)
    MODULE_CONFIG(silent_pic_mode)
    MODULE_CONFIG(silent_pic_slitscan_mode)
    MODULE_CONFIG(silent_pic_file_format)
MODULE_CONFIGS_END()

MODULE_PROPHANDLERS_START()
    MODULE_PROPHANDLER(PROP_ISO)
    MODULE_PROPHANDLER(PROP_SHUTTER)
MODULE_PROPHANDLERS_END()
6D

Kouglov

Update : I have made a working PoC wich doesn't take pictures in live view, but two pics with few delay



Here's the code :



/** Dual Fast Picture **/

#include <module.h>
#include <dryos.h>
#include <bmp.h>
#include <menu.h>
#include <config.h>
#include <property.h>
#include <raw.h>
#include <shoot.h>
#include <zebra.h>
#include <beep.h>
#include <lens.h>
#include <focus.h>
#include <string.h>
#include <battery.h>
#include <powersave.h>


static uint64_t ret_0_long() { return 0; }

static CONFIG_INT( "dualfs.invert", silent_pic_invert, 0);
static CONFIG_INT( "dualfs.fiso", silent_pic_first_iso, 0);
static CONFIG_INT( "dualfs.fshutter", silent_pic_first_shutter, 0);
static CONFIG_INT( "dualfs.iso", silent_pic_recovery_iso, 0);
static CONFIG_INT( "dualfs.shutter", silent_pic_recovery_shutter, 0);

//static int long_exposure_fix_enabled = 0;

/* forward reference */
static struct menu_entry silent_menu[];
static struct menu_entry silent_smenu[];

static int iso_original = 0;
static int shutter_original = 0;

static int new_iso = 0;
static int new_shutter = 0;

static int new_fiso = 0;
static int new_fshutter = 0;

static MENU_UPDATE_FUNC(silent_pic_mode_update)
{
    /* reveal options for the current shooting mode, if any */
   // silent_menu[0].children[1].shidden =(silent_pic_mode != SILENT_PIC_MODE_SLITSCAN);
}


static MENU_UPDATE_FUNC(isocheck)
{

switch (silent_pic_recovery_iso)
    {
        case -12:
            new_iso = ISO_100;
            break;
        case -11:
            new_iso = ISO_125;
            break;
        case -10:
            new_iso = ISO_160;
            break;
        case -9:
            new_iso = ISO_200;
            break;
        case -8:
            new_iso = ISO_250;
            break;
        case -7:
            new_iso = ISO_320;
            break;
        case -6:
            new_iso = ISO_400;
            break;
        case -5:
            new_iso = ISO_500;
            break;
        case -4:
            new_iso = ISO_640;
            break;
        case -3:
            new_iso = ISO_800;
            break;
        case -2:
            new_iso = ISO_1000;
            break;
        case -1:
            new_iso = ISO_1250;
            break;
        case 0:
            new_iso = ISO_1600;
            break;
        case 1:
            new_iso = ISO_2000;
            break;
        case 2:
            new_iso = ISO_2500;
            break;
        case 3:
            new_iso = ISO_3200;
            break;
        case 4:
            new_iso = ISO_4000;
            break;
       

    }
//bmp_printf(FONT_MED, 0, 0, "Iso debug : %d", silent_pic_recovery_iso);
    bmp_printf(FONT_MED, 0, 0, "Iso chosen : %d", new_iso);

}

static MENU_UPDATE_FUNC(fisocheck)
{

switch (silent_pic_first_iso)
    {
        case -12:
            new_fiso = ISO_100;
            break;
        case -11:
            new_fiso = ISO_125;
            break;
        case -10:
            new_fiso = ISO_160;
            break;
        case -9:
            new_fiso = ISO_200;
            break;
        case -8:
            new_fiso = ISO_250;
            break;
        case -7:
            new_fiso = ISO_320;
            break;
        case -6:
            new_fiso = ISO_400;
            break;
        case -5:
            new_fiso = ISO_500;
            break;
        case -4:
            new_fiso = ISO_640;
            break;
        case -3:
            new_fiso = ISO_800;
            break;
        case -2:
            new_fiso = ISO_1000;
            break;
        case -1:
            new_fiso = ISO_1250;
            break;
        case 0:
            new_fiso = ISO_1600;
            break;
        case 1:
            new_fiso = ISO_2000;
            break;
        case 2:
            new_fiso = ISO_2500;
            break;
        case 3:
            new_fiso = ISO_3200;
            break;
        case 4:
            new_fiso = ISO_4000;
            break;
       

    }
    //bmp_printf(FONT_MED, 0, 0, "Iso debug : %d", silent_pic_recovery_iso);
    bmp_printf(FONT_MED, 0, 0, "Fiso chosen : %d", new_fiso);

}


static MENU_UPDATE_FUNC(shuttercheck)
{

switch (silent_pic_recovery_shutter)
    {
        case -12:
            new_shutter = SHUTTER_1_60;
            break;
        case -11:
            new_shutter = SHUTTER_1_80;
            break;
        case -10:
            new_shutter = SHUTTER_1_90;
            break;
        case -9:
            new_shutter = SHUTTER_1_100;
            break;
        case -8:
            new_shutter = SHUTTER_1_125;
            break;
        case -7:
            new_shutter = SHUTTER_1_160;
            break;
        case -6:
            new_shutter = SHUTTER_1_180;
            break;
        case -5:
            new_shutter = SHUTTER_1_200;
            break;
        case -4:
            new_shutter = SHUTTER_1_250;
            break;
        case -3:
            new_shutter = SHUTTER_1_320;
            break;
        case -2:
            new_shutter = SHUTTER_1_350;
            break;
        case -1:
            new_shutter = SHUTTER_1_400;
            break;
        case 0:
            new_shutter = SHUTTER_1_500;
            break;
        case 1:
            new_shutter = SHUTTER_1_640;
            break;
        case 2:
            new_shutter = SHUTTER_1_750;
            break;
        case 3:
            new_shutter = SHUTTER_1_800;
            break;
        case 4:
            new_shutter = SHUTTER_1_1000;
            break;
        case 5:
            new_shutter = SHUTTER_1_1250;
            break;
        case 6:
            new_shutter = SHUTTER_1_1500;
            break;
        case 7:
            new_shutter = SHUTTER_1_1600;
            break;
        case 8:
            new_shutter = SHUTTER_1_2000;
            break;
        case 9:
            new_shutter = SHUTTER_1_2500;
            break;
        case 10:
            new_shutter = SHUTTER_1_3000;
            break;
        case 11:
            new_shutter = SHUTTER_1_3200;
            break;
        case 12:
            new_shutter = SHUTTER_1_4000;
            break;
       

    }
//bmp_printf(FONT_MED, 0, 0, "Shutter debug : %d", silent_pic_recovery_shutter);
    bmp_printf(FONT_MED, 0, 0, "Shutter chosen : %d", new_shutter);

}

static MENU_UPDATE_FUNC(fshuttercheck)
{

switch (silent_pic_first_shutter)
    {
        case -12:
            new_fshutter = SHUTTER_0s3;
            break;
        case -11:
            new_fshutter = SHUTTER_0s4;
            break;
        case -10:
            new_fshutter = SHUTTER_0s5;
            break;
        case -9:
            new_fshutter = SHUTTER_0s6;
            break;
        case -8:
            new_fshutter = SHUTTER_0s7;
            break;
        case -7:
            new_fshutter = SHUTTER_0s8;
            break;
        case -6:
            new_fshutter = SHUTTER_1s;
            break;
        case -5:
            new_fshutter = SHUTTER_1s3;
            break;
        case -4:
            new_fshutter = SHUTTER_1s5;
            break;
        case -3:
            new_fshutter = SHUTTER_1s6;
            break;
        case -2:
            new_fshutter = SHUTTER_2s;
            break;
        case -1:
            new_fshutter = SHUTTER_2s5;
            break;
        case 0:
            new_fshutter = SHUTTER_3s;
            break;
        case 1:
            new_fshutter = SHUTTER_3s2;
            break;
        case 2:
            new_fshutter = SHUTTER_4s;
            break;
        case 3:
            new_fshutter = SHUTTER_5s;
            break;
        case 4:
            new_fshutter = SHUTTER_6s;
            break;
        case 5:
            new_fshutter = SHUTTER_8s;
            break;
        case 6:
            new_fshutter = SHUTTER_10s;
            break;
        case 7:
            new_fshutter = SHUTTER_13s;
            break;
        case 8:
            new_fshutter = SHUTTER_15s;
            break;
        case 9:
            new_fshutter = SHUTTER_20s;
            break;
        case 10:
            new_fshutter = SHUTTER_25s;
            break;
        case 11:
            new_fshutter = SHUTTER_30s;
            break;
        case 12:
            new_fshutter = SHUTTER_MIN;
            break;
       

    }
    //bmp_printf(FONT_MED, 0, 0, "Shutter debug : %d", silent_pic_recovery_shutter);
    bmp_printf(FONT_MED, 0, 0, "Fshutter chosen : %d", new_fshutter);

}



static void fshoot()
{
    shutter_original = lens_info.raw_shutter;

    iso_original = lens_info.raw_iso;

    if(silent_pic_invert == 0){

    lens_set_rawiso(new_fiso);
    lens_set_rawshutter(new_fshutter);

    //is_bulb_mode();

    take_fast_pictures(1);


    lens_set_rawiso(new_iso);
    lens_set_rawshutter(new_shutter);

    take_fast_pictures(1);

    }
    else{

    lens_set_rawiso(new_iso);
    lens_set_rawshutter(new_shutter);

    //is_bulb_mode();

    take_fast_pictures(1);

    lens_set_rawiso(new_fiso);
    lens_set_rawshutter(new_fshutter);


    take_fast_pictures(1);

    }

    lens_set_rawiso(iso_original);
    lens_set_rawshutter(shutter_original);

    return;
}

   

   
   

static struct menu_entry silent_menu[] = {
    {
        .name = "ISO Flash Menu",
        //.priv = &silent_pic_enabled,
        //.update = silent_pic_display,
        .max  = 1,
        .depends_on = DEP_LIVEVIEW | DEP_CFN_AF_BACK_BUTTON,
        .help  = "Take two pictures with custom parameters \n"
"with minimum delay between them",
        .submenu_width = 650,
        .children =  (struct menu_entry[]) {
            {
                .name = "First ISO",
                .priv = &silent_pic_first_iso,
                .update = fisocheck,
                .min = -12,
                .max = 4,
                //.unit = UNIT_ISO,
                .choices = CHOICES("100", "125","160","200","250","320","400","500","640","800","1000","1250","1600","2000","2500","3200","4000"),
                .help  = "ISO for first shot (should be low)",
                //.help2 = "Test",
            },
            {
                .name = "First Shutter",
                .priv = &silent_pic_first_shutter,
                .update = fshuttercheck,
                .min = -12,
                .max = 12,
                //.unit = UNIT_ISO,
                .choices = CHOICES("0.3", "0.4", "0.5", "0.6", "0.7", "0.8", "1", "1.3", "1.5", "1.6", "2", "2.5", "3", "3.2", "4", "5", "6", "8", "10", "13", "15", "20", "25", "30", "MIN"),
                .help  = "shutter for first shot (in seconds, should be long)",
                //.help2 = "(Indicated in 1 / value)",
            },
            {
                .name = "Second ISO",
                .priv = &silent_pic_recovery_iso,
                .update = isocheck,
                .min = -12,
                .max = 4,
                //.unit = UNIT_ISO,
                .choices = CHOICES("100", "125","160","200","250","320","400","500","640","800","1000","1250","1600","2000","2500","3200","4000"),
                .help  = "ISO for second shot (should be high)",
                //.help2 = "Test",
            },
    {
                .name = "Second Shutter",
                .priv = &silent_pic_recovery_shutter,
                .update = shuttercheck,
                .min = -12,
                .max = 12,
                //.unit = UNIT_ISO,
                .choices = CHOICES("60", "80", "90", "100", "125", "160", "180", "200", "250", "320", "350", "400", "500", "640", "750", "800", "1000", "1250", "1500", "1600", "2000", "2500", "3000", "3200", "4000"),
                .help  = "shutter for second shot (in 1/value, should be short)",
                //.help2 = "(Indicated in 1 / value)",
            },

{
                .name = "Invert",
                .priv = &silent_pic_invert,
                //.update = shuttercheck,
                .min = 0,
                .max = 1,
                //.unit = UNIT_ISO,
                .choices = CHOICES("Yes", "No"),
                .help  = "Invert order of picture (takes second before first)",
                //.help2 = "(Indicated in 1 / value)",
            },
            MENU_EOL,
        }
       
    }
};


static struct menu_entry silent_smenu[] = {
    {
        .name = "ISO Flash Shoot",
        //.priv = &silent_pic_enabled,
        //.update = silent_pic_display,
        .max  = 1,
        .depends_on = DEP_LIVEVIEW | DEP_CFN_AF_BACK_BUTTON,
        .help  = "Take two pictures with custom parameters \n"
"with minimum delay between them",
        .submenu_width = 650,
        .children =  (struct menu_entry[]) {
            {
                .name = "SHOOT",
                //.priv = &silent_pic_first_shutter,
                .update = fshoot,
                //.min = -12,
                //.max = 12,
                .help  = "start the shoot sequence",
                //.help2 = "(Indicated in 1 / value)",
            },
            MENU_EOL,
        }
       
    }
};


static unsigned int silent_init()
{
   
    /* fixme in core: prop handlers should trigger when initializing, but they do not */
    shutter_original = lens_info.raw_iso;
    iso_original = lens_info.raw_shutter;
    menu_add("Shoot", silent_menu, COUNT(silent_menu));
    menu_add("Shoot", silent_smenu, COUNT(silent_smenu));
    return 0;
}

static unsigned int silent_deinit()
{
    return 0;
}

MODULE_INFO_START()
    MODULE_INIT(silent_init)
    MODULE_DEINIT(silent_deinit)
MODULE_INFO_END()

MODULE_CONFIGS_START()
    MODULE_CONFIG(silent_pic_invert)
    MODULE_CONFIG(silent_pic_first_iso)
    MODULE_CONFIG(silent_pic_first_shutter)
    MODULE_CONFIG(silent_pic_recovery_iso)
    MODULE_CONFIG(silent_pic_recovery_shutter)
MODULE_CONFIGS_END()


6D

eyeland

Daybreak broke me loose and brought me back...

Seanc

You're trying to get the look of 2nd curtain sync flash while taking a long exposure flash without a strobe.

I think you're on the right track for what you can do, but you won't be able to duplicate the effect because the strobe is an essential part of the look. Ideally the strobe isn't just at the end of the exposure, it's also only (primarily) lighting the side of the subject it's moving towards so the leading edge is well defined but not the rest.

The brighter picture you're taking will be sharp all over. If you globally combine them it'll effect the whole scene instead of just the leading edge. Instead layer the pictures with a mask over the sharp one. Then paint away the mask over the leading edge so the sharp picture shows through into the long exposure, and blend towards the back and I think you'll have something. If the subject moved too much you may have to re-position that layer but because you're not including the background and the long exposure layer is motion blurred you'll be able to without harming the result - it'll be tolerant of that. I think what you've done will work for many situations via layered combining. I'd love to have a module to play with on my 5D mk 3.

Alex, I don't remember from the Dual ISO awsomeness thread. Does the image readout forcibly clear/destroy the sensor data so there is no possibility of a double read out or is that unknown?

a1ex

What exactly happens during a readout, at hardware level, is currently unknown. Double readout is probably worth investigating, but I'm not sure where to start. Possible path:

- replicate whatever Canon code does to the hardware (see these huge logs)
- get that working in both photo mode and LiveView (the former starts the exposure on all rows at the same time, the latter uses rolling shutter for both start and end of the exposure)
- compare the two hardware configurations and figure out the difference (hard, there are many differences)
- tweak each register and try to figure out what it does (currently possible with adtg_gui)
- attempt to run the readout code twice

Not straightforward, but probably worth exploring if you have nothing else to do for a few weeks or so :P

Seanc

Ooooh, it's not ruled out then!  :P I've wondered if Sony's trick is partly a double read combined into an HDRish raw. (maybe ISO 200 and 800 or 1600)

That's going to be a lot to untangle! It's a shame market forces mean we can't collaborate with Canon on this.

I'm a database guy in my day job, so only work with high level languages. It'd take me weeks to get a dev environment working and start learning the baby steps of learning the programming. I can follow the gist of what other folks write often, but that's a long way from being able to create on a blank slate. I did get that multi-threaded dual ISO processor working with priority though that was purely fighting with Windows. (wanted to still use my main rig while it churned on dual ISO work)

Now I wonder whether I'd be able to learn enough to make a dent in getting that done.

From a Lua thread Alex post: "If you want to take a burst of full-size images, and you have (or can borrow) a 5D3, my suggestion would be the 4K branch, as it can also record full-res frames (with rolling shutter) at about 4-5 FPS continuously, without shutter actuation."

That might be just the ticket for this quick double picture idea! I like your idea the more I think about it Kouglov. There are some night club and stage lighting scenes I've shot where that'd let me get some great results where a simple shot would just be average. That's be well worth the work to get, as I'd rather have a few hero shots than a folder of ok ones.

Seanc

"- get that working in both photo mode and LiveView (the former starts the exposure on all rows at the same time, the latter uses rolling shutter for both start and end of the exposure)"

I hadn't realized they're so different. That might give an edge to work on to unravel what's happening in the hardware.
Do you think the rolling shutter is so the rear LCD live view can be processed through a pipe as it's captured? (just seems like the obvious reason why) That part of the difference wouldn't provide hardware clues so there'd be lots related code to weed out. The rolling shutter itself should be interesting though. Even if the global read can't be done non-destructively, the rolling shutter must be reading line by line. Maybe you could global capture, trick just the rolling readout to run then global read. -shrug- We'd need the research work you pointed out to speculate usefully. (Thanks for answering btw! This is interesting!)

a1ex

Image capture and LCD display are unrelated. Image is displayed after the capture is fully completed AND the image processed (color-corrected etc). There's no global readout in Canon sensors, from what I could tell; only the start of the exposure is global when capturing still photos. However, In that case, the mechanical shutter is what gives the exposure time. The electrical shutter is open for a slightly longer time, but not capturing light (maybe just integrating some noise).

Timing analysis: https://www.magiclantern.fm/forum/index.php?topic=12523.msg121962#msg121962

Kouglov

Thanks to all of those who answered in this thread :D

i'm very sorry to bring it back after such a long time, but I managed to buy a EOS 100D (to bring along when I don't want to risk my 6D)

Just for saying that I tested my module on the 100D and it works perfectly.

Of course it doesn't achieve completly the effect I first researched, but I think it is  a good start, maybe I'll work on it more on the next weeks.

Anyway, I published the module on github right here : https://github.com/kouglov/MagicLanternDualFastPicture

And I think you're aware of that, but I cannot garranty it will work on your camera, nor damage it  :o

You can also found a compiled module "dualfs.mo" juste here : https://github.com/kouglov/MagicLanternDualFastPicture/blob/master/dualfs.mo

6D

Danne

Seems a cool project. Could you explain how you use it? I have a 100D and would like to test it out :)

Kouglov

thanks for your message Danne !

At first, I wanted to create this module to achieve some sort of "ISO flash"
Like, taking a scene where the subject move rapidly and at night.

This module allow to take a first picture with long exposure to make a picture on wich you can  see the trails of the object (like the lights if it's a car).
This picture is followed immediatly by another shot wich can be very fast (and with high ISO to achieve that at night) to fix the subject to make it sharp.

I wanted to make it in liveView mode to reduce the delay between the shots, but for a first module, it was simpler to make it as a stand alone module without the liveView mode.

With the customs parameters, it is possible to take the long exposure shot in first or second position.
once activated, the module add two sub-menus in the "Shoot" pannel.
The first, "ISO Flash Menu" allow to modify the parameters and choose shutter speed and ISO of both shots, and eventualy invert the takes.
The second one, "ISO Flash Shoot" start the take.

6D

nikfreak

[size=8pt]70D.112 & 100D.101[/size]

Kouglov

Not yet, I wanted to test it at night at the 24 hours of Le Mans this year, but I didn't managed to find a great spot at night.

I'm planning to attempt more this summer, but I don't know quite when.

What I know, is that creating one picture with the two would require more that a simple addition and treatment in lightroom.
6D