summaryrefslogtreecommitdiff
path: root/camlibs
diff options
context:
space:
mode:
authorMarcus Meissner <marcus@jet.franken.de>2022-10-10 17:01:30 +0200
committerMarcus Meissner <marcus@jet.franken.de>2022-10-10 17:02:34 +0200
commit540762d91f62019d05cbb29fd60adae17fbf9c9f (patch)
treeb64c73edb496044cb233f5b8786b495df9ccc8c4 /camlibs
parente0e4da2d5c87d7406c644f419a5ca58be0a90d4d (diff)
downloadlibgphoto2-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')
-rw-r--r--camlibs/ptp2/library.c34
-rw-r--r--camlibs/ptp2/ptp.c28
-rw-r--r--camlibs/ptp2/ptp.h2
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 (&params->events, &params->nrofevents, evt);
+/*
params->events = realloc(params->events, sizeof(PTPContainer)*(params->nrofevents+1));
memcpy (&params->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 (&params->events, &params->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);