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

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