Wikia

CHDK Wiki

Manual Exposure Control for Video Recording

Talk3
575pages on
this wiki
Revision as of 22:27, June 30, 2014 by Oid maps (Talk | contribs)

This wiki page presents a script written to provide manual control of exposure settings during the video recording. It should work with all CHDK enabled Canon P&S cameras. Please check if your model has been tested (below) and if not, please report any testing results.

Forum Thread  : Video Manual Control

Download Link :  videxp3.lua


Operation

Videxp2

To use this script, place the camera into video recording mode. When the script is activated, a GUI input box will open on the bottom of the camera LCD screen. Use the camera keyboard keys Directional buttons to control the GUI. The right & left keys change fields. The up & down keys to change the exposure values in each field. Use the DISP/SET button to start and stop video recording. The MENU key or a shutter button full press will end script execution.


Note :  using this script requires that Lua Native Calls be enabled in the CHDK Miscellaneous menu.  See the warning below about the use of native calls.

Configuration

Configuration Options are :
Videxp3
  • Starting Tv (sec) :  set the default shutter speed to be used when the script starts
  • Staring Av (f-stop) : set the default lens aperture opening to be used when the script starts
  • Staring ISO : set the default ISO sensitiviy setting to be use used when the script starts
  • ISO Max : set the maximum value the script will allow for ISO adjustment.  One some cameras, too high a value will cause the script to shut down
  • Show start message : enables a startup help screen
  • Debug mode :  enable the script console - useful if the script does not seem to be working.

Warning

Use this script at you own risk.  This script makes native calls to the Canon firmware in order to manipulate exposure settings during video recording.  While it is generally believed safe to do so,  and this code has been tested on many camera models, it is potentially more risky that standard CHDK activities.  

Results may also vary between different camera models so if you test this script and find it works for your camera please report it here.

Tested Cameras

(please add any additional cameras tested here - please note any failures too)

  • A Series:
    • A570 (ISO 3200 works)
    • A720
    • A1200
    • A2000 (ISO 3200 works)
    • A2500 (*)
  • G series:
    • G10
    • G12
  • IXUS series:
    • IXUS120_SD940
  • S series:
    • S110 
  • SX series:
    • SX100is
    • SX130is
    • SX150is
    • SX160is
    • SX220hs
    • SX260hs
    • SX50hs

(*) There is no video recording mode on the A2500, only the red button to start/stop video recording. But you can use anyway the script:

- press shutter in ALT mode, an error message says "Camera not in video mode" ; press arrow keys to show/modify Tv, Av and Sv parameters ; press FUNC. SET button to start/stop recording
- press shutter or MENU button to exit script
- press shutter ; press arrow keys to show/modify again Tv, Av and Sv parameters ; press FUNC. SET button to start/stop recording
- etc...
WARNING: don't activate Debug mode in the script, it freezes the recording.

Failures :

  • SX50hs hangs when ISO3200 selected, works fine otherwise if mode dial set to Video
  • G12 failed with script versions prior to 3.3
  • G1X fails
  • Elph 300/Ixus 220 HS worked until video record is pressed. Then auto expose happens.

Lua Script

videxp3.lua : for CHDK v1.3.0 or greater

hint :  you can download the most recent version of the script from the link posted at the top of this page

--[[
@title Video Exp Ctrl v3.1
 
original script by fudgey 2010/08/23
http://chdk.setepontos.com/index.php?topic=5295.msg68622#msg68622
modified 2013/11/29 by waterwingz & msl
 
@param     t Starting Tv (sec)
  @default t 3
  @values  t 1/30 1/60 1/100 1/200 1/400 1/640 1/800 1/1000 1/1250 1/1600 1/2000
@param     a Starting Av (f-stop)
  @default a 7
  @values  a 1.8 2.0 2.2 2.6 2.8 3.2 3.5 4.0 4.5 5.0 5.6 6.3 7.1 8.0
@param   p Starting ISO 
  @default p 1
  @values  p 80 100 200 400 800 1250 1600
@param     q ISO Max
  @default q 4
  @values  q 100 200 400 800 1250 1600 3200
@param     s Show Start Message ?
  @default s 1
  @range   s 0 1
@param     d Debug Mode ?
  @default d 0
  @range   d 0 1
--]]
 
require("drawings")
props=require("propcase")
 
--  ========================== Functions ================================= 
 
function restore()
  if ( get_movie_status() == 4 ) then
    if ( vbutton == 1 ) then press("video") sleep(500) release("video")
    else press("shoot_full") sleep(250) release("shoot_full") end
  end
  set_aelock(0)
  set_console_autoredraw(0)
end
 
tv_ref = {    -- note : tv_ref values set 1/2 way between shutter speed values
     464,  496,  528,  560,  592,  624,  656,
     688,  720,  752,  784,  816,  848,  880,  912,  944,  976,
    1008, 1040, 1072, 1096, 1129, 1169, 1192, 1225, 1265, 1376  }
 
tv_val = { 
       400,
       471,  511,  542,  567,  607,  638,  669,
       703,  734,  765,  799,  830,  861,  895,  926,  957,  988,
      1022, 1053, 1084, 1118, 1149, 1180, 1214, 1245, 1276 }
 
tv_str = {
      "err",
      "1/30", "1/40", "1/50", "1/60", "1/80", "1/100", "1/125",
     "1/160", "1/200", "1/250","1/320","1/400","1/500","1/640","1/800","1/1000","1/1250",
    "1/1600","1/2000","1/2500","1/3200","1/4000","1/5000","1/6400","1/8000","1/10000","hi"  }
 
function print_tv(val)
    if ( val == nil ) then return("-") end
    local i = 1
    while (i <= #tv_ref) and (val > tv_ref[i]) do i=i+1 end
    return tv_str[i]
end
 
av_table = {163, 192, 218, 254, 285, 322, 347, 384, 417, 446, 477, 510, 543, 576, 609, 638, 664, 710, 731, 768}
 
function print_av(val)
    if ( val == nil ) then return("-") end
    local fstop=av96_to_aperture(val)
    return((fstop/1000).."."..(fstop%1000)/100)
end
 
sv_table = { 380, 411, 507, 603, 699, 795, 891 } 
function print_sv(val)
    if ( val == nil ) then return("-") end
    return( ((iso_real_to_market(sv96_to_iso(val))+5)/10)*10 )
end
 
function screen_w()     -- lookup table for 480 px screen
    local cams = "ixus110_sd960|ixus200_sd980|ixus240_elph320hs|ixus300_sd4000|ixus310_elph500hs|ixus1000_sd4500|sx1|sx210is|sx220hs|sx230hs"
    return string.find(cams, get_buildinfo().platform) and 480 or 360
end
 
function help_screen()
    local x = screen_w()/2 - 132
    local help_msg = { "HELP SCREEN","FUNC/SET : start/stop video","\017 \016 : change field", "\030 \031 : change value",  "MENU : exit", "FULLPRESS : exit", "Press any key to start", " "}
    local i=1
    while (i < #help_msg) do 
        msg = "                          "..(help_msg[i]).."                          "
        inx = string.find(msg,":")
        if (inx ~= nil) then
            draw.add( "string", x, i*16+64, string.sub(msg, inx-12, inx+18), "red","white")
        else
            draw.add( "string", x, i*16+64, string.sub(msg, (#msg/2)-12, (#msg/2)+18),"white", "blue")
        end
        i=i+1
    end
    rec,vid,mode=get_mode()
    if (vid ~= true) then
        msg ="                           ".."**Camera not in video mode**".."                          "    
        draw.add( "string", x, i*16+64, string.sub(msg, (#msg/2)-12, (#msg/2)+18), "yellow","red")
    end
    repeat
        draw.overdraw()
        wait_click(100)
    until not(is_key("no_key"))
    draw.clear()
end
 
function draw_box()
  local fg, bg = "blue" , "black"
  local w = box_width
  local h = box_height
  --if (gb ~= "trans") then 
  draw.add("rectf",  xpos-1,     ypos-6, xpos+w+1, ypos+h+1, bg, bg)
  --end
  draw.add("string", xpos,       ypos-6, "   Tv     Av    Sv", fg, bg)
  draw.add("line",   xpos,       ypos,   xpos+20,   ypos,   fg)
  draw.add("line",   xpos+45,    ypos,   xpos+70,   ypos,   fg)
  draw.add("line",   xpos+100,   ypos,   xpos+120,  ypos,   fg)
  draw.add("line",   xpos+150,   ypos,   xpos+w,  ypos,   fg)
  draw.add("line",   xpos,       ypos,   xpos,      ypos+h, fg)
  draw.add("line",   xpos+w,     ypos,   xpos+w,    ypos+h, fg)
  draw.add("line",   xpos,       ypos+h, xpos+w,    ypos+h, fg)
end
 
function init_values()
    local fg, bg = "blue" , "black"
    val1=draw.add("string", xpos+6,   ypos+12, " -",   fg, bg)
    val2=draw.add("string", xpos+76,  ypos+12, " -" ,  fg, bg)
    val3=draw.add("string", xpos+120, ypos+12, " -" ,  fg, bg)
end
 
function show_values(Tv, Av, Sv)
    local fg, bg = "white" , "black"
    local fg1, fg2, fg3, fg4, bg1, bg2, bg2 , bg3, bg4
    if(gui_index==0) then fg1 = bg bg1=fg else fg1 = fg bg1=bg end
    if(gui_index==1) then fg2 = bg bg2=fg else fg2 = fg bg2=bg end
    if(gui_index==2) then fg3 = bg bg3=fg else fg3 = fg bg3=bg end
    draw.replace(val1, "string",  xpos+6,  ypos+12, string.sub(" "..print_tv(Tv).."      ",0,8), fg1, bg1)
    draw.replace(val2, "string", xpos+76,  ypos+12, string.sub(" "..print_av(Av).."      ",0,5), fg2, bg2)
    draw.replace(val3, "string", xpos+120, ypos+12, string.sub(" "..print_sv(Sv).."      ",0,5), fg3, bg3)
end
 
function adjust_value(inx, offset)
    local i=1
    if     (inx==0 ) then                                               -- adjust Tv value
        while (i <= #tv_ref) and ( tv96 > tv_ref[i]) do i=i+1 end
        if ( offset > 0 ) then tv96=tv_val[math.min(#tv_val,i+1)]      
        else  tv96=tv_val[math.max(2,i-1)] end
        while (i <= #tv_ref) and ( tv96 > tv_val[i]) do i=i+1 end 
        tv96ret=call_event_proc("SetAE_ShutterSpeed",tv96) 
        if ((tv96ret < tv96-96) or (tv96ret > tv96+96))then             -- clamp values beyond cameras range
            print("clamp", tv96ret)
            tv96=tv96ret 
        end       
        print("new Tv96=",tv96)
    elseif (inx==1) then                                                -- adjust Av value
        av96old = av96
        while (i <= #av_table) and ( av96 > av_table[i]) do i=i+1 end
        if ( offset > 0)  then  
            repeat                                                      -- find next f-stop value the camera will accept
                av96=av_table[math.min(#av_table,i)]
                av96ret=call_event_proc("MoveIrisToAv",av96)
                i=i+1
            until (i > #av_table) or (av96ret>av96old)
            av96=av96ret
        else
            repeat
                i=i-1
                av96=av_table[math.max(1,i)]
                av96ret=call_event_proc("MoveIrisToAv",av96)
            until (i==1) or (av96ret<av96old)
            av96=av96ret
        end
        print("new Av96=",av96)
    elseif (inx==2) then                                                -- adjust Sv value
        while (i <= #sv_table) and ( sv96 > sv_table[i]) do i=i+1 end
        if ( offset > 0)  then  sv96=sv_table[math.min(#sv_table,i+1)]
        else  sv96=sv_table[math.max(1,i-1)] end
        call_event_proc("SetCDSGain",sv96)
        print("new Sv96=",sv96)
    end
end
 
--  ========================== Main Program ================================= 
 
    tv_table    = { 471, 567, 640, 736, 832, 896, 928, 960, 992, 1024, 1056, 1180, 1276}
    tv96target  = tv_table[t+1]
    av_table    = { 171, 192, 218, 265, 285, 322, 347, 384, 417, 446, 477, 510, 543, 576 }
    av96target  = av_table[a+1]
    sv_table    = { 381, 411, 507, 603, 699, 761, 795, 891 }
    sv96target  = sv_table[p+1]
    sv96max     = sv_table[p+2]
 
    xpos =  screen_w()/2 -110               -- msl: 360 or 480 px for default screen position & size (upper left hand corner)
    ypos =  175                             -- msl: above the warning text of the unlimited video recording time
    box_width = 170
    box_height = 32
    set_console_layout(1 ,4, 45, 16 )
 
    bi=get_buildinfo()
    print(string.format("%s %s-%s %s %s %s", bi.version, bi.build_number, bi.build_revision, bi.platform, bi.platsub, bi.build_date))
    version= tonumber(string.sub(string.gsub(get_buildinfo().build_number, "%p", ""), 0, 3))
    if ( tonumber(bi.build_revision) > 0 ) then build = tonumber(bi.build_revision)
    else build = tonumber(string.match(bi.build_number,'-(%d+)$')) end
 
    if ( version < 130) or ( build < 3250)  then 
        error("CHDK 1.3.0 or higher, build 3250 or higher, required")
    end
    if (type(call_event_proc) ~= "function" ) then                      -- need native calls turned on
        error("Lua native calls not enabled")
    end 
    if (call_event_proc("FA.Create") == -1) then                        -- required for event procedures SetAE_ShutterSpeed, MoveIrisToAv, SetCDSGain
        error("FA CREATE failed")
    end
    if (call_event_proc("InitializeAdjustmentSystem") == -1) then
        error("InitializeAdjustmentSystem failed")
    end
 
 -- switch to shooting mode & make sure we are in a video mode
    if ( get_mode() == false ) then
       sleep(1000)
       set_record(1)
       while ( get_mode() == false) do sleep(100) end
    end
    sleep(500)
 
 -- setup splash screen & console 
    set_console_autoredraw(d -1)
    cls()  
    if (s==1) then help_screen() end    
    set_exit_key("no_key")                                              -- use "menu" key to exit so that recording gets stopped if running
    set_draw_title_line(0)
    vbutton = get_video_button()
 
-- startup values 
    set_aelock(1)                                                      -- go to manual exposure mode 
    tv96=call_event_proc("SetAE_ShutterSpeed",tv96target)
    av96=call_event_proc("MoveIrisToAv",av96target)
    call_event_proc("SetCDSGain",sv96target) 
    sv96=sv96target
 
    draw_box()
    init_values()
    gui_index=0
 
    while true do
        show_values(tv96, av96, sv96) 
        repeat
           draw.overdraw()
           wait_click(200)
        until not(is_key("no_key"))
        if     is_pressed("set")   then
            if ( vbutton == 1 ) then press("video") sleep(1000) release("video") sleep(1000)
            else press("shoot_full") sleep(1000) release("shoot_full") sleep(1000) end
        elseif is_pressed("left")  then
            if gui_index > 0 then gui_index = gui_index - 1 end
        elseif is_pressed("right") then
            if gui_index < 2 then gui_index = gui_index + 1 end
        elseif ( is_key("up")) then
           adjust_value(gui_index, 1)
        elseif ( is_key("down")) then
           adjust_value(gui_index, -1)
        elseif ( is_key("zoom_in")) then
            press("zoom_in")
            while(is_pressed("zoom_in")) do sleep(20) end
            release("zoom_in")
        elseif ( is_key("zoom_out")) then
            press("zoom_out")
            while(is_pressed("zoom_out")) do sleep(20) end
            release("zoom_out")
        elseif (is_pressed("menu") or is_pressed("shoot_full"))  then break
        end
    end
    restore()

Around Wikia's network

Random Wiki