gphoto / libgphoto2

The libgphoto2 camera access and control library.
GNU Lesser General Public License v2.1
1.05k stars 325 forks source link

Repeated capture on Sony ILCE-5000 fails #485

Open wferi opened 4 years ago

wferi commented 4 years ago

Hi, After applying the

--- i/examples/sample-capture.c
+++ w/examples/sample-capture.c
@@ -116,6 +116,8 @@ main(int argc, char **argv) {
                exit (1);
        }
        capture_to_file(camera, context, "foo.jpg");
+       gp_camera_exit(camera, context);
+       return 0;

        capture_to_memory(camera, context, (const char**)&data, &size);

patch sample-capture works fine when built and invoked as:

$ gcc $(pkg-config --cflags libgphoto2) -Wall -o sample-capture context.c sample-capture.c $(pkg-config --libs libgphoto2)
$ ./sample-capture ; ./sample-capture
Camera init.  Takes about 10 seconds.
The supplied vendor or product id (0x0,0x0) is not valid.
Capturing.
Reading PTP event failed: Timeout reading from or writing to the port (-10)
[...]
Reading PTP event failed: Timeout reading from or writing to the port (-10)
  Retval: 0
Pathname on the camera: //capt0000.jpg
  Retval: 0
  Retval: 0
Deleting.
  Retval: 0
Camera init.  Takes about 10 seconds.
The supplied vendor or product id (0x0,0x0) is not valid.
Capturing.
Reading PTP event failed: Timeout reading from or writing to the port (-10)
[...]
Reading PTP event failed: Timeout reading from or writing to the port (-10)
  Retval: 0
Pathname on the camera: //capt0000.jpg
  Retval: 0
  Retval: 0
Deleting.
  Retval: 0

However, if I apply the

--- i/examples/sample-capture.c
+++ w/examples/sample-capture.c
@@ -116,6 +116,9 @@ main(int argc, char **argv) {
                exit (1);
        }
        capture_to_file(camera, context, "foo.jpg");
+       capture_to_file(camera, context, "bar.jpg");
+       gp_camera_exit(camera, context);
+       return 0;

        capture_to_memory(camera, context, (const char**)&data, &size);

patch instead and compile as above I get:

$ ./sample-capture
Camera init.  Takes about 10 seconds.
The supplied vendor or product id (0x0,0x0) is not valid.
Capturing.
Reading PTP event failed: Timeout reading from or writing to the port (-10)
[...]
Reading PTP event failed: Timeout reading from or writing to the port (-10)
  Retval: 0
Pathname on the camera: //capt0000.jpg
  Retval: 0
  Retval: 0
Deleting.
  Retval: 0
Capturing.
'libusb_bulk_transfer (port->pl->dh, port->settings.usb.inep, (unsigned char*)bytes, size, &curread, port->timeout)' failed: No such device (it may have been disconnected) (-4)
Reading 1024 = 0x400 bytes from port failed: Could not find the requested device on the USB port (-52)
PTP_OC 0x1008 receiving data failed: PTP No Device (0x02f9)
'ptp_getobjectinfo (params, newobject, &oi)' failed: PTP I/O Error (0x02ff)
'camera->functions->capture (camera, type, path, context)' failed: -7
  Retval: -7
Pathname on the camera: //foo.jpg
  Retval: 0
'gp_filesystem_get_file (camera->fs, folder, file, type, camera_file, context)' failed: -108
  Retval: -108
Deleting.
'gp_filesystem_delete_file ( camera->fs, folder, file, context)' failed: -108
  Retval: -108
'libusb_bulk_transfer (port->pl->dh, port->settings.usb.outep, (unsigned char*)bytes, size, &curwritten, port->timeout)' failed: No such device (it may have been disconnected) (-4)
Writing 12 = 0xc bytes to port failed: Could not find the requested device on the USB port (-52)
PTP_OC 0x1003 sending req failed: Could not find the requested device on the USB port (-52)
Could not release interface 0 (No such device).

That is, sample-capture takes a picture and saves it, then the camera appears to switch off and reinitialize itself (just like with the stock sample-capture). The camera can't really do anything after this until it's manually power-cycled, though. However, with the

--- i/examples/sample-capture.c
+++ w/examples/sample-capture.c
@@ -116,6 +116,15 @@ main(int argc, char **argv) {
                exit (1);
        }
        capture_to_file(camera, context, "foo.jpg");
+       gp_camera_exit(camera, context);
+       retval = gp_camera_init(camera, context);
+       if (retval != GP_OK) {
+               printf("  Retval of gp_camera_init: %d\n", retval);
+               exit (1);
+       }
+       capture_to_file(camera, context, "bar.jpg");
+       gp_camera_exit(camera, context);
+       return 0;

        capture_to_memory(camera, context, (const char**)&data, &size);

patch the ./sample-capture command successfully captures twice and can even be repeated.

Did I try to use the API wrong? Exactly when is the exit/init pair necessary? Any idea what else could be wrong? If the previous approach should work, what would help diagnosing the issue? Since tag v2.5.24 commit 25c7db3b seems somewhat related, but in the opposite direction... Thanks, Feri.

$ gphoto2 --auto-detect
Model                          Port                                            
----------------------------------------------------------
USB PTP Class Camera           usb:003,101     
$ gphoto2 --summary | fgrep Model
Model: ILCE-5000
$ gphoto2 --version
gphoto2 2.5.23

Copyright (c) 2000-2019 Marcus Meissner and others

gphoto2 comes with NO WARRANTY, to the extent permitted by law. You may
redistribute copies of gphoto2 under the terms of the GNU General Public
License. For more information about these matters, see the files named COPYING.

This version of gphoto2 is using the following software versions and options:
gphoto2         2.5.23         gcc, popt(m), exif, cdk, aa, jpeg, readline
libgphoto2      2.5.24         standard camlibs (SKIPPING lumix), gcc, ltdl, EXIF
libgphoto2_port 0.12.0         iolibs: disk ptpip serial usb1 usbdiskdirect usbscsi, gcc, ltdl, EXIF, USB, serial without locking
wferi commented 4 years ago

I'd gladly experiment with some changes given a little guidance about which parts of the code I should touch. Could somebody please link to a patch implementing a similar model-specific tweak for example? Thanks.

msmeissn commented 4 years ago

The exit -> init cycle should not be necessary. Also various people capture repeatedly images with Sony cameras...

does gphoto2 --capture-image-and-download -F 5 -I 3
work better, e.g. capture 5 images?

wferi commented 4 years ago

Yes, that command captures 5 images all right.

msmeissn commented 4 years ago

libusb_bulk_transfer reporting PTP No Device could mean the sony is crashing and you seem to describe this behaviour.

What is weird that gphoto2 itself does not crash when doing the same thing.

can you insert a gp_camera_wait_for_event call in your code? like in .e.g. sample-tether.c

    CameraEventType evttype;
    void    *evtdata;

            retval = gp_camera_wait_for_event (camera, 1000, &evttype, &evtdata, context);
            if (retval != GP_OK)
                    break;

(this would wait at most 1 second)

wferi commented 4 years ago

Inserting a gp_camera_wait_for_event() call between the two capture_to_file() calls helps! Here is the timestamped condensed output:

$ stdbuf -oL ./sample-capture  | ts -s %.S
00.000019 Camera init.  Takes about 10 seconds.
00.077421 The supplied vendor or product id (0x0,0x0) is not valid.
00.119391 Capturing.
01.280457 Reading PTP event failed: Timeout reading from or writing to the port (-10)
[221 similar lines suppressed]
02.286139 Reading PTP event failed: Timeout reading from or writing to the port (-10)
02.748454   Retval: 0
02.748575 Pathname on the camera: //capt0000.jpg
02.748608   Retval: 0
02.753854   Retval: 0
02.754143 Deleting.
02.754230   Retval: 0
02.772695 Capturing.
04.066512 Reading PTP event failed: Timeout reading from or writing to the port (-10)
[228 similar lines suppressed]
05.017670 Reading PTP event failed: Timeout reading from or writing to the port (-10)
05.516857   Retval: 0
05.517091 Pathname on the camera: //capt0001.jpg
05.517182   Retval: 0
05.523909   Retval: 0
05.524146 Deleting.
05.524238   Retval: 0

Thanks for looking into this!

wferi commented 4 years ago

And the returned evttype is 4, that is, GP_EVENT_CAPTURE_COMPLETE.

wferi commented 4 years ago

In other words, the following patch fixes sample-capture for me:

diff --git i/examples/sample-capture.c w/examples/sample-capture.c
index 17d9ec6ec..df03a1baf 100644
--- i/examples/sample-capture.c
+++ w/examples/sample-capture.c
@@ -100,6 +100,8 @@ main(int argc, char **argv) {
        FILE    *f;
        char    *data;
        unsigned long size;
+       CameraEventType evttype;
+       void    *evtdata;

        gp_log_add_func(GP_LOG_ERROR, errordumper, NULL);
        gp_camera_new(&camera);
@@ -116,6 +118,10 @@ main(int argc, char **argv) {
                exit (1);
        }
        capture_to_file(camera, context, "foo.jpg");
+       retval = gp_camera_wait_for_event (camera, 1000, &evttype, &evtdata, context);
+       if (retval != GP_OK)
+               return 1;
+       printf("Event type: %d (GP_EVENT_CAPTURE_COMPLETE is %d)\n", evttype, GP_EVENT_CAPTURE_COMPLETE);

        capture_to_memory(camera, context, (const char**)&data, &size);