root/core/remotecap.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. remotecap_get_target_support
  2. remotecap_get_target
  3. remotecap_set_timeout
  4. remotecap_is_ready
  5. remotecap_set_available_data_type
  6. remotecap_reset
  7. remotecap_set_target
  8. remotecap_using_dng_module
  9. remotecap_wait
  10. remotecap_type_complete
  11. remotecap_raw_available
  12. remotecap_fwt_file_complete
  13. remotecap_fwt_file_available
  14. remotecap_fwt_jpeg_available
  15. remotecap_fwt_craw_available
  16. remotecap_get_data_chunk
  17. remotecap_send_complete

   1 #include "ptp.h"
   2 #include "stdlib.h"
   3 #include "platform.h"
   4 #include "conf.h"
   5 #include "remotecap_core.h"
   6 #include "module_load.h"
   7 #include "modules.h"
   8 #include "raw.h"
   9 #include "cachebit.h"
  10 
  11 #define HOOK_WAIT_MAX_DEFAULT 3000 // timeout for remotecap hooks, in 10ms sleeps = 30 sec
  12 static int hook_wait_max=HOOK_WAIT_MAX_DEFAULT; 
  13 
  14 static int available_image_data=0; // type of data available
  15 
  16 static int pending_image_data=0; // data types requested but not yet transferred in current shot
  17 
  18 static int remote_file_target=0; // requested data types
  19 
  20 static int target_file_num; // file number captured in raw hook
  21 
  22 static ptp_data_chunk raw_chunk;
  23 static ptp_data_chunk dng_hdr_chunk;
  24 
  25 // raw subimage range
  26 static int startline=0;
  27 static int linecount=0;
  28 
  29 #ifdef CAM_HAS_FILEWRITETASK_HOOK
  30 static int fwt_curr_chunk;
  31 static int fwt_last_status;
  32 static int fwt_current_type; // data type of current filewrite file, for cams with raw and jpeg
  33 static int fwt_expect_file_count; // number of filewrite files expected (for cameras with native raw+jpeg)
  34 #ifdef CAM_FILEWRITETASK_MULTIPASS
  35 static int fwt_session_wait; // should the current invocation of the filewrite hook block
  36 #endif //CAM_FILEWRITETASK_MULTIPASS
  37 #endif //CAM_HAS_FILEWRITETASK_HOOK
  38 
  39 
  40 int remotecap_get_target_support(void) {
  41     int ret = (PTP_CHDK_CAPTURE_RAW | PTP_CHDK_CAPTURE_DNGHDR);
  42 #ifdef CAM_HAS_FILEWRITETASK_HOOK
  43     ret |= PTP_CHDK_CAPTURE_JPG;
  44 #ifdef CAM_HAS_CANON_RAW
  45     ret |= PTP_CHDK_CAPTURE_CRAW;
  46 #endif
  47 #endif
  48     return ret;
  49 }
  50 
  51 int remotecap_get_target(void) {
  52     return remote_file_target;
  53 }
  54 
  55 /*
  56 set hook timeout in ms
  57 */
  58 void remotecap_set_timeout(int timeout) 
  59 {
  60     if(timeout <= 0) {
  61         hook_wait_max = HOOK_WAIT_MAX_DEFAULT;
  62     } else {
  63         hook_wait_max = timeout/10;
  64     }
  65 }
  66 
  67 void remotecap_is_ready(int *available_type,int *file_num) {
  68     if ( remotecap_get_target() ) {
  69         *available_type = available_image_data;
  70         if(available_image_data) {
  71             *file_num = target_file_num;
  72         } else {
  73             *file_num = 0;
  74         }
  75     }
  76     else {
  77         *available_type = PTP_CHDK_CAPTURE_NOTSET;
  78         *file_num = 0;
  79     }
  80 }
  81 
  82 // could | in if we supported multiple types available at the same time
  83 static void remotecap_set_available_data_type(int type)
  84 {
  85     available_image_data = type;
  86 }
  87 
  88 // free hooks, reset target and available
  89 static void remotecap_reset(void) {
  90     remote_file_target=0;
  91     remotecap_set_available_data_type(0);
  92     pending_image_data=0;
  93     // TODO do we need remotecap_fwt_chunks_done() ?
  94 }
  95 
  96 //called to activate or deactive hooks
  97 int remotecap_set_target( int type, int lstart, int lcount )
  98 {
  99     // fail if invalid / unsupported type requested,
 100     // or current mode cannot support requested types
 101     if ((type & ~remotecap_get_target_support()) 
 102         || !camera_info.state.mode_rec
 103         || ((type & PTP_CHDK_CAPTURE_RAW) && !is_raw_possible())
 104 #ifdef CAM_HAS_CANON_RAW
 105         || ((type & PTP_CHDK_CAPTURE_CRAW) && !(shooting_get_canon_image_format() & SHOOTING_CANON_FMT_RAW))
 106         || ((type & PTP_CHDK_CAPTURE_JPG) && !(shooting_get_canon_image_format() & SHOOTING_CANON_FMT_JPG))
 107 #endif
 108 #if defined(CAM_FILEWRITETASK_MULTIPASS) && !defined(CAM_FILEWRITETASK_SEEKS)
 109     // other drive modes do not work on these cams currently
 110         || (shooting_get_drive_mode() != 0)
 111 #endif
 112         ) {
 113         remotecap_reset();
 114         return 0;
 115     }
 116     // clear requested
 117     if(type==0) {
 118         remotecap_reset();
 119         return 1;
 120     }
 121     // invalid range, return error
 122     if(lstart<0 || lstart>CAM_RAW_ROWS-1 || lcount<0 || lcount+lstart>CAM_RAW_ROWS) {
 123         remotecap_reset();
 124         return 0;
 125     }
 126     // default lcount = to end of buffer
 127     if(lcount == 0) {
 128         lcount = CAM_RAW_ROWS - lstart;
 129     }
 130     remote_file_target=type;
 131     startline=lstart;
 132     linecount=lcount;
 133     return 1;
 134 }
 135 
 136 /*
 137 don't allow unloading DNG module if target is DNG
 138 not optimal since it could lead to loading/unloading every shot
 139 could make logic more sophisticated later
 140 */
 141 int remotecap_using_dng_module(void) {
 142     return (remote_file_target & PTP_CHDK_CAPTURE_DNGHDR) != 0;
 143 }
 144 
 145 /*
 146 return 0 if timed out, otherwise non-zero
 147 called from tasks that need to wait for data to be read
 148 */
 149 static int remotecap_wait(int datatype) {
 150     int wait = hook_wait_max;
 151 
 152     remotecap_set_available_data_type(datatype);
 153 
 154     while (wait && (available_image_data & datatype)) {
 155         msleep(10);
 156         wait--;
 157     }
 158     return wait;
 159 }
 160 
 161 // called from filewrite or spytask when type is fully completed
 162 static void remotecap_type_complete(int type) {
 163     pending_image_data = (pending_image_data & ~type);
 164 }
 165 
 166 void filewrite_set_discard_file(int state);
 167 int filewrite_get_file_chunk(char **addr,unsigned *size, unsigned n, int *pos);
 168 
 169 void remotecap_raw_available(char *rawadr) {
 170     // get file number as early as possible, before blocking
 171     // but don't set until after so it doesn't change value for remotecap_is_ready
 172     int next_file_num = get_target_file_num(); 
 173 /*
 174 ensure raw hook is blocked until any prevous remotecap shot is finished or times out
 175 if prevous times out, remotecap settings will be cleared due to the time out, so no
 176 remotecap will be done, although writes will still be skipped
 177 wait == 0 timeout shouldn't get hit here unless the script is fiddling with the
 178 timeout value, but it ensures that we don't block indefinitely.
 179 */
 180     int wait = hook_wait_max;
 181     while (wait && pending_image_data) {
 182         msleep(10);
 183         wait--;
 184     }
 185     if(wait == 0) {
 186         remotecap_reset();
 187     }
 188     pending_image_data = remote_file_target;
 189     target_file_num = next_file_num;
 190 // TODO technically this could probably wait until after the raw stuff is done,
 191 // provided the actual chunks are transmitted
 192 // TODO this should probably just be noop if hook doesn't exist
 193 #ifdef CAM_HAS_FILEWRITETASK_HOOK
 194     filewrite_set_discard_file(1);
 195     fwt_curr_chunk=0; //needs to be done here
 196 #ifdef CAM_HAS_CANON_RAW
 197     if(shooting_get_canon_image_format() == (SHOOTING_CANON_FMT_RAW | SHOOTING_CANON_FMT_JPG)) {
 198         fwt_expect_file_count = 2;
 199     } else {
 200         fwt_expect_file_count = 1;
 201     }
 202 #else
 203     fwt_expect_file_count = 1;
 204 #endif
 205 #endif //CAM_HAS_FILEWRITETASK_HOOK
 206     if (remote_file_target & PTP_CHDK_CAPTURE_DNGHDR) {
 207         started();
 208         libdng->create_dng_header_for_ptp(&dng_hdr_chunk);
 209 
 210         if(!remotecap_wait(PTP_CHDK_CAPTURE_DNGHDR)) {
 211             remotecap_reset();
 212         }
 213         libdng->free_dng_header_for_ptp();
 214         remotecap_type_complete(PTP_CHDK_CAPTURE_DNGHDR);
 215         finished();
 216     }
 217 
 218     if(!(remote_file_target & PTP_CHDK_CAPTURE_RAW)) {
 219         return;
 220     }
 221 
 222     started();
 223     
 224     raw_chunk.address=(unsigned int)ADR_TO_UNCACHED(rawadr+startline*CAM_RAW_ROWPIX*CAM_SENSOR_BITS_PER_PIXEL/8);
 225     raw_chunk.length=linecount*CAM_RAW_ROWPIX*CAM_SENSOR_BITS_PER_PIXEL/8;
 226   
 227     if(!remotecap_wait(PTP_CHDK_CAPTURE_RAW)) {
 228         remotecap_reset();
 229     }
 230     remotecap_type_complete(PTP_CHDK_CAPTURE_RAW);
 231     
 232     finished();
 233 }
 234 
 235 #ifdef CAM_HAS_FILEWRITETASK_HOOK
 236 // called from filewrite when file is complete and remotecap is enabled, regardless of whether type is target
 237 void remotecap_fwt_file_complete(void) {
 238     remotecap_type_complete(fwt_current_type); // clearing non-target type should be harmless...
 239     // possible this could be reset on error, or not set in mode with broken raw hook
 240     if(fwt_expect_file_count) {
 241         fwt_expect_file_count--;
 242     }
 243     if(fwt_expect_file_count == 0) {
 244         filewrite_set_discard_file(0);
 245     }
 246 }
 247 
 248 /*
 249 called from filewrite hook to notify code new file data is available
 250 */
 251 static void remotecap_fwt_file_available(void) {
 252     if(!(remote_file_target & fwt_current_type)) {
 253         return;
 254     }
 255 #ifdef CAM_FILEWRITETASK_MULTIPASS
 256     // need custom wait code here to resume if jpeg queue is done
 257     int wait = hook_wait_max;
 258 
 259     fwt_session_wait = 1;
 260     remotecap_set_available_data_type(fwt_current_type);
 261 
 262     while (wait && fwt_session_wait && (available_image_data & fwt_current_type)) {
 263         msleep(10);
 264         wait--;
 265     }
 266     if(wait==0) {
 267         remotecap_reset();
 268     }
 269 
 270 #else
 271     if(!remotecap_wait(fwt_current_type)) {
 272         remotecap_reset();
 273     }
 274 #endif
 275 }
 276 
 277 void remotecap_fwt_jpeg_available(void) {
 278     fwt_current_type = PTP_CHDK_CAPTURE_JPG;
 279     remotecap_fwt_file_available();
 280 }
 281 
 282 #ifdef CAM_HAS_CANON_RAW
 283 void remotecap_fwt_craw_available(void) {
 284     fwt_current_type = PTP_CHDK_CAPTURE_CRAW;
 285     remotecap_fwt_file_available();
 286 }
 287 #endif
 288 
 289 #endif // CAM_HAS_FILEWRITETASK_HOOK
 290 
 291 // called by ptp code to get next chunk address/size for the format (fmt) that is being currently worked on
 292 // returns REMOTECAP_CHUNK_STATUS MORE, ERROR or LAST
 293 int remotecap_get_data_chunk( int fmt, char **addr, unsigned int *size, int *pos )
 294 {
 295     int status = REMOTECAP_CHUNK_STATUS_LAST; // default = no more chunks
 296     *pos = -1; // default = sequential
 297     
 298     switch (fmt & remotecap_get_target() & available_image_data)
 299     {
 300         case PTP_CHDK_CAPTURE_RAW: //raw
 301             *addr=(char*)raw_chunk.address;
 302             *size=raw_chunk.length;
 303             break;
 304 #ifdef CAM_HAS_FILEWRITETASK_HOOK
 305         case PTP_CHDK_CAPTURE_CRAW: //canon raw
 306         case PTP_CHDK_CAPTURE_JPG: //jpeg
 307             fwt_last_status = filewrite_get_file_chunk(addr,size,fwt_curr_chunk,pos);
 308             fwt_curr_chunk+=1;
 309             if(fwt_last_status != REMOTECAP_FWT_CHUNK_STATUS_LAST) {
 310                 status = REMOTECAP_CHUNK_STATUS_MORE;
 311             } 
 312 #ifdef CAM_HAS_CANON_RAW
 313             else {
 314                 fwt_curr_chunk=0;
 315             }
 316 #endif
 317             break;
 318 #endif
 319         case PTP_CHDK_CAPTURE_DNGHDR: // dng header
 320             *addr=(char*)dng_hdr_chunk.address;
 321             *size=dng_hdr_chunk.length;
 322             break;
 323         default:
 324             /*
 325              * attempting to get an unsupported, unavailable or not requested format
 326              * will free all hooks, deactiveate remotecap, and return error status
 327              */
 328             *addr=NULL;
 329             *size=0;
 330     }
 331     if(*addr == NULL) {
 332         remotecap_reset();
 333         status = REMOTECAP_CHUNK_STATUS_ERROR;
 334     }
 335 
 336     return status;
 337 }
 338 
 339 int remotecap_send_complete(int rcgd_status, int type) {
 340     // timeout or canceled: the data type we were sending is no longer available
 341     int timeout_flag = (available_image_data != type);
 342     if(rcgd_status == REMOTECAP_CHUNK_STATUS_LAST) {
 343         // currently only one data type can be available at a time
 344         remotecap_set_available_data_type(0);
 345     }
 346 #ifdef CAM_FILEWRITETASK_MULTIPASS
 347     else if(type == PTP_CHDK_CAPTURE_JPG && fwt_last_status == REMOTECAP_FWT_CHUNK_STATUS_SESS_LAST) {
 348         remotecap_fwt_chunks_done(); // make file_chunks NULL, immediately
 349         fwt_session_wait = 0;
 350     }
 351 #endif
 352     if((rcgd_status == REMOTECAP_CHUNK_STATUS_ERROR) || timeout_flag) {
 353         return 0;
 354     }
 355     // else more chunks of current type, no action needed
 356     return 1;
 357 }

/* [<][>][^][v][top][bottom][index][help] */