diff options
author | Marcus Meissner <marcus@jet.franken.de> | 2022-10-10 17:01:30 +0200 |
---|---|---|
committer | Marcus Meissner <marcus@jet.franken.de> | 2022-10-10 17:02:34 +0200 |
commit | 540762d91f62019d05cbb29fd60adae17fbf9c9f (patch) | |
tree | b64c73edb496044cb233f5b8786b495df9ccc8c4 /camlibs/ptp2 | |
parent | e0e4da2d5c87d7406c644f419a5ca58be0a90d4d (diff) | |
download | libgphoto2-540762d91f62019d05cbb29fd60adae17fbf9c9f.tar.gz |
use a local PTP event queue in nikon capture to avoid checking interrupts on any event,
which causes delays.
https://github.com/gphoto/libgphoto2/issues/846
Diffstat (limited to 'camlibs/ptp2')
-rw-r--r-- | camlibs/ptp2/library.c | 34 | ||||
-rw-r--r-- | camlibs/ptp2/ptp.c | 28 | ||||
-rw-r--r-- | camlibs/ptp2/ptp.h | 2 |
3 files changed, 53 insertions, 11 deletions
diff --git a/camlibs/ptp2/library.c b/camlibs/ptp2/library.c index 503e54e20..4ec0990f9 100644 --- a/camlibs/ptp2/library.c +++ b/camlibs/ptp2/library.c @@ -4061,6 +4061,9 @@ camera_nikon_capture (Camera *camera, CameraCaptureType type, CameraFilePath *pa int back_off_wait = 0; struct timeval capture_start; int loops; + PTPContainer *storedevents = NULL; + unsigned int nrstoredevents = 0; + PTPContainer event; if (type != GP_CAPTURE_IMAGE) @@ -4086,6 +4089,7 @@ camera_nikon_capture (Camera *camera, CameraCaptureType type, CameraFilePath *pa _("Sorry, your camera does not support Nikon capture")); return GP_ERROR_NOT_SUPPORTED; } + if ( ptp_property_issupported(params, PTP_DPC_StillCaptureMode) && (PTP_RC_OK == ptp_getdevicepropdesc (params, PTP_DPC_StillCaptureMode, &propdesc))) { PTPDevicePropDesc burstdesc; @@ -4120,6 +4124,13 @@ camera_nikon_capture (Camera *camera, CameraCaptureType type, CameraFilePath *pa C_PTP_REP_MSG (nikon_wait_busy(params,20,2000), _("Nikon enable liveview failed")); } + /* before we start real capture, move the current hw event queue to our local queue */ + while (ptp_get_one_event(params, &event)) { + GP_LOG_D ("saving event queue before capture: event.Code is %x / param %lx", event.Code, (unsigned long)event.Param1); + ptp_add_event_queue (&storedevents, &nrstoredevents, &event); + } + + if (ptp_operation_issupported(params, PTP_OC_NIKON_InitiateCaptureRecInMedia)) { /* we assume for modern cameras this event method works to avoid longer waits */ params->event90c7works = 1; @@ -4156,7 +4167,12 @@ camera_nikon_capture (Camera *camera, CameraCaptureType type, CameraFilePath *pa } capturetriggered: - C_PTP_REP (ret); + if (ret != PTP_RC_OK) { + /* store back all the queued events back to the hw event queue before returning. */ + /* we do not do this in all error edge cases currently, only the ones that can trigger often */ + ptp_add_events (params, &storedevents, nrstoredevents); + C_PTP_REP (ret); + } CR (gp_port_set_timeout (camera->port, capture_timeout)); @@ -4166,13 +4182,9 @@ capturetriggered: done = 0; tries = 100; capture_start = time_now(); do { - PTPContainer event; - int checkevt; - /* Just busy loop until the camera is ready again. */ /* and wait for the 0xc101 event */ C_PTP_REP (ptp_check_event (params)); - checkevt = 0; while (ptp_get_one_event(params, &event)) { GP_LOG_D ("event.Code is %x / param %lx", event.Code, (unsigned long)event.Param1); switch (event.Code) { @@ -4191,8 +4203,7 @@ capturetriggered: /* if we got one object already, put it into the queue */ /* e.g. for NEF+RAW capture */ if (newobject != 0xffff0001) { - ptp_add_event (params, &event); - checkevt = 1; /* avoid endless loop */ + ptp_add_event_queue (&storedevents, &nrstoredevents, &event); done = 3; break; } @@ -4223,12 +4234,9 @@ capturetriggered: break; default: GP_LOG_D ("UNHANDLED event.Code is %x / param %lx, DEFER", event.Code, (unsigned long)event.Param1); - ptp_add_event (params, &event); - checkevt = 1; /* avoid endless loop */ + ptp_add_event_queue (&storedevents, &nrstoredevents, &event); break; } - if (checkevt) - break; } /* we got both capturecomplete and objectadded ... leave */ if (done == 3) @@ -4241,6 +4249,10 @@ capturetriggered: gp_context_idle (context); /* do not drain all of the DSLRs compute time */ } while ((done != 3) && waiting_for_timeout (&back_off_wait, capture_start, 70*1000)); /* 70 seconds */ + + /* add all the queued events back to the event queue */ + ptp_add_events (params, &storedevents, nrstoredevents); + /* Maximum image time is 30 seconds, but NR processing might take 25 seconds ... so wait longer. * see https://github.com/gphoto/libgphoto2/issues/94 */ diff --git a/camlibs/ptp2/ptp.c b/camlibs/ptp2/ptp.c index 9e5df52e3..5bdce1c97 100644 --- a/camlibs/ptp2/ptp.c +++ b/camlibs/ptp2/ptp.c @@ -3228,11 +3228,39 @@ ptp_canon_checkevent (PTPParams* params, PTPContainer* event, int* isevent) } uint16_t +ptp_add_event_queue (PTPContainer **events, unsigned int *nrevents, PTPContainer *evt) +{ + PTPContainer *levents; + + levents = realloc(*events, sizeof(PTPContainer)*((*nrevents)+1)); + if (!levents) + return PTP_RC_GeneralError; + *events = levents; + memcpy (&events[*nrevents],evt,1*sizeof(PTPContainer)); + (*nrevents)++; + return PTP_RC_OK; +} +uint16_t ptp_add_event (PTPParams *params, PTPContainer *evt) { + return ptp_add_event_queue (¶ms->events, ¶ms->nrofevents, evt); +/* params->events = realloc(params->events, sizeof(PTPContainer)*(params->nrofevents+1)); memcpy (¶ms->events[params->nrofevents],evt,1*sizeof(PTPContainer)); params->nrofevents += 1; + + return PTP_RC_OK; +*/ +} + +uint16_t +ptp_add_events (PTPParams *params, PTPContainer **evt, unsigned int nrevents) +{ + unsigned int i; + + for (i=0;i<nrevents;i++) { + CHECK_PTP_RC (ptp_add_event_queue (¶ms->events, ¶ms->nrofevents, evt[i])); + } return PTP_RC_OK; } diff --git a/camlibs/ptp2/ptp.h b/camlibs/ptp2/ptp.h index 8f0e03529..914abdede 100644 --- a/camlibs/ptp2/ptp.h +++ b/camlibs/ptp2/ptp.h @@ -4033,6 +4033,8 @@ uint16_t ptp_check_event (PTPParams *params); uint16_t ptp_check_event_queue (PTPParams *params); uint16_t ptp_wait_event (PTPParams *params); uint16_t ptp_add_event (PTPParams *params, PTPContainer *evt); +uint16_t ptp_add_events (PTPParams *params, PTPContainer **evt, unsigned int nrevents); +uint16_t ptp_add_event_queue (PTPContainer **events, unsigned int *nrevents, PTPContainer *evt); int ptp_have_event(PTPParams *params, uint16_t code); int ptp_get_one_event (PTPParams *params, PTPContainer *evt); int ptp_get_one_event_by_type(PTPParams *params, uint16_t code, PTPContainer *event); |