seeing-things / zwo

ZWO SDK and custom software for debugging and using it.
23 stars 4 forks source link

Raspberry PI 4 : GetVideoData failed with error code ASI_ERROR_TIMEOUT #50

Closed VigibotDev closed 4 years ago

VigibotDev commented 4 years ago

I try to run PI 4 headless system, for now with a remote x server on gigabit LAN I get :

root@raspberrypi:~/zwo/capture/bin# cat /sys/module/usbcore/parameters/usbfs_memory_mb 200

root@raspberrypi:~/zwo/capture/bin# ./capture [ZWOFixer] PLTHook(libusb_cancel_transfer): constructed [ZWOFixer] PLTHook(libusb_cancel_transfer): installed main thread id: 847 [ZWOFixer] ZWOFixerInit: OK capture: Found 1 cameras; arbitrarily selecting ZWO ASI178MM. disk thread id: 850 capture: No filename provided; not writing to disk!

preview thread id: 851 gain thread id: 852 capture: GetVideoData failed with error code ASI_ERROR_TIMEOUT capture: GetVideoData failed with error code ASI_ERROR_TIMEOUT capture: GetVideoData failed with error code ASI_ERROR_TIMEOUT Frame count: 000001, Dropped frames: 000000 To-disk queue: 0 frames, to-AGC queue: 0 frames, pool: 64 free frames. capture: GetVideoData failed with error code ASI_ERROR_TIMEOUT capture: GetVideoData failed with error code ASI_ERROR_TIMEOUT capture: GetVideoData failed with error code ASI_ERROR_TIMEOUT capture: GetVideoData failed with error code ASI_ERROR_TIMEOUT Frame count: 000002, Dropped frames: 000001 To-disk queue: 0 frames, to-AGC queue: 0 frames, pool: 64 free frames. capture: GetVideoData failed with error code ASI_ERROR_TIMEOUT capture: GetVideoData failed with error code ASI_ERROR_TIMEOUT capture: GetVideoData failed with error code ASI_ERROR_TIMEOUT capture: GetVideoData failed with error code ASI_ERROR_TIMEOUT Frame count: 000003, Dropped frames: 000002 To-disk queue: 0 frames, to-AGC queue: 0 frames, pool: 64 free frames. capture: GetVideoData failed with error code ASI_ERROR_TIMEOUT capture: GetVideoData failed with error code ASI_ERROR_TIMEOUT capture: GetVideoData failed with error code ASI_ERROR_TIMEOUT capture: GetVideoData failed with error code ASI_ERROR_TIMEOUT capture: GetVideoData failed with error code ASI_ERROR_TIMEOUT Frame count: 000003, Dropped frames: 000002 To-disk queue: 0 frames, to-AGC queue: 0 frames, pool: 64 free frames. capture: GetVideoData failed with error code ASI_ERROR_TIMEOUT capture: GetVideoData failed with error code ASI_ERROR_TIMEOUT capture: GetVideoData failed with error code ASI_ERROR_TIMEOUT capture: GetVideoData failed with error code ASI_ERROR_TIMEOUT capture: GetVideoData failed with error code ASI_ERROR_TIMEOUT Frame count: 000003, Dropped frames: 000002 To-disk queue: 0 frames, to-AGC queue: 0 frames, pool: 64 free frames. capture: GetVideoData failed with error code ASI_ERROR_TIMEOUT capture: GetVideoData failed with error code ASI_ERROR_TIMEOUT capture: GetVideoData failed with error code ASI_ERROR_TIMEOUT capture: GetVideoData failed with error code ASI_ERROR_TIMEOUT capture: GetVideoData failed with error code ASI_ERROR_TIMEOUT Frame count: 000004, Dropped frames: 000003 To-disk queue: 0 frames, to-AGC queue: 0 frames, pool: 64 free frames. capture: GetVideoData failed with error code ASI_ERROR_TIMEOUT ^CDisk thread ending. Preview thread ending. AGC thread ending. capture: GetVideoData failed with error code ASI_ERROR_TIMEOUT Main (camera) thread done, waiting for others to finish. Main thread ending. [ZWOFixer] PLTHook(libusb_cancel_transfer): uninstalled [ZWOFixer] PLTHook(libusb_cancel_transfer): destructed root@raspberrypi:~/zwo/capture/bin#

VigibotDev commented 4 years ago

I removed the preview code to run without GUI and problem still here. And there is now stdout streaming:( it's an important missing feature for performance on embedded system (we do not want to write !)

bgottula commented 4 years ago

@Serveurperso thanks for the report. You may be the first person other than myself or @jgottula to attempt to use the contents of this repo. Everything we have done so far has been on AMD64 systems which is probably the source of the problem; see #51 for details on that.

As for the print statements: You are of course welcome to comment them out or fork this and modify code as desired to suit your needs. The stdout activity is intentional and I find the information valuable in my application so I don't plan to remove them.

What is your intended use-case for this code? The primary goal of the capture program was to write raw frame data to disk as efficiently as possible. Since you are running on a Pi I expect you must have something different in mind?

VigibotDev commented 4 years ago

Hi, first thanks for answering, please don't pay attention to my bad english :), I need a realtime /low latency use of this camera with low resolution (hardware binning) for my robotics website ( https://www.vigibot.com free/no ads) to put on a realtime sky observer robot.

I just need a RAW (or MJPEG) stream to feed stdin of ffmpeg. Just a small C code can write RAW stream on stdout...

I already done this with a sensitive CMOS PAL camera "Runcam Nigh Eagle Astro" : https://www.youtube.com/watch?v=AH2G6O4WEg0 (go to middle of this video), Robot is named "Astro" you can use it to look the sky:D

I am really disappointed with the documentation and compatibility of this ZWO ASI178MM camera, We can't use as a camera on Linux (V4L2 / UV4L) ... For me headless pipe stream is the minimum mandatory basis to give customers of a Linux camera....

My dream would be to be able to get a 640x480 @ 30FPS stream from this camera (stdout), I'm already able to do "real time stacking" with my ffmpeg. I already put a 50mm F1.1 lens on the camera

Don't need to write on microsd, it's a bad idea for lifetime. Memory (pipe) is way faster and better for realtime use.

VigibotDev commented 4 years ago

I am working on making my own code:) Just need to understand why the framerate is slow (even with short exposure). I think I must use the video mode instead of snap mode...

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include "ASICamera2.h"

#define WIDTH 640
#define HEIGHT 480
#define PIXELCONF ASI_IMG_RAW8
#define PIXELSIZE 1
#define BIN 4
#define EXPOSURE 33000
#define GAIN 0

volatile bool run = true;

void signal_callback_handler(int signum) {
 fprintf(stderr, "Caught signal %d\n", signum);
 run = false;
}

int main() {
 if(ASIGetNumOfConnectedCameras() < 1) {
  fprintf(stderr, "Camera not detected\n");
  return 1;
 }

 ASI_CAMERA_INFO *asi_camera_info = (ASI_CAMERA_INFO *) malloc(sizeof(ASI_CAMERA_INFO));
 if(ASIGetCameraProperty(asi_camera_info, 0) == ASI_SUCCESS) {
  fprintf(stderr, "ASI Camera Name: %s\n", asi_camera_info->Name);
  fprintf(stderr, "Camera ID: %d\n", asi_camera_info->CameraID);
  fprintf(stderr, "Width and Height: %d x %d\n", asi_camera_info->MaxWidth, asi_camera_info->MaxHeight);
  fprintf(stderr, "Color: %s\n", asi_camera_info->IsColorCam == ASI_TRUE ? "Yes" : "No");
  fprintf(stderr, "Bayer pattern: %d\n", asi_camera_info->BayerPattern);
  fprintf(stderr, "Pixel size: %1.1f um\n", asi_camera_info->PixelSize);
  fprintf(stderr, "e-/ADU: %1.2f\n", asi_camera_info->ElecPerADU);
  fprintf(stderr, "Bit depth: %d\n", asi_camera_info->BitDepth);
  fprintf(stderr, "Trigger cam: %s\n", asi_camera_info->IsTriggerCam == 0 ? "No" : "Yes");
 } else {
  fprintf(stderr, "Error getting properties of the camera\n");
  return 1;
 }

 int id = asi_camera_info->CameraID;
 if(ASIOpenCamera(id) != ASI_SUCCESS) {
  fprintf(stderr, "Error opening camera\n");
  return 1;
 }

 if(ASIInitCamera(id) != ASI_SUCCESS) {
  fprintf(stderr, "Error initializing camera\n");
  return 1;
 }

 fprintf(stderr, "\n");
 int asi_num_controls = 0;
 if(ASIGetNumOfControls(id, &asi_num_controls) != ASI_SUCCESS) {
  fprintf(stderr, "Error getting number of controls of camera\n");
  return 1;
 }
 ASI_CONTROL_CAPS **asi_control_caps = (ASI_CONTROL_CAPS **) malloc(sizeof(ASI_CONTROL_CAPS *) * asi_num_controls);
 for(int i = 0; i < asi_num_controls; i++) {
  asi_control_caps[i] = (ASI_CONTROL_CAPS *) malloc(sizeof(ASI_CONTROL_CAPS));
  ASIGetControlCaps(id, i, asi_control_caps[i]);
  fprintf(stderr, "%s: [%d, %d] = %d%s - %s\n", asi_control_caps[i]->Name,
                                                asi_control_caps[i]->MinValue,
                                                asi_control_caps[i]->MaxValue,
                                                asi_control_caps[i]->DefaultValue,
                                                asi_control_caps[i]->IsWritable == 1 ? " (set)" : "",
                                                asi_control_caps[i]->Description);
 }

 ASISetROIFormat(id, WIDTH, HEIGHT, BIN, PIXELCONF);

 ASISetControlValue(id, ASI_EXPOSURE, EXPOSURE, ASI_FALSE);
 ASISetControlValue(id, ASI_GAIN, GAIN, ASI_FALSE);
 ASISetControlValue(id, ASI_BANDWIDTHOVERLOAD, 90, ASI_FALSE);
 ASISetControlValue(id, ASI_HIGH_SPEED_MODE, false, ASI_FALSE);

 signal(SIGINT, signal_callback_handler);
 signal(SIGTERM, signal_callback_handler);

 ASI_EXPOSURE_STATUS asi_exp_status;
 long image_size = WIDTH * HEIGHT * PIXELSIZE;
 unsigned char *asi_image = (unsigned char *) malloc(sizeof(unsigned char) * image_size);

 while(run) {
  ASIStartExposure(id, ASI_FALSE);

  do {
   ASIGetExpStatus(id, &asi_exp_status);
  } while(run && asi_exp_status != ASI_EXP_SUCCESS);

  ASIGetDataAfterExp(id, asi_image, image_size);
  fwrite(asi_image, image_size, 1, stdout);
 }

 ASICloseCamera(id);
 return 0;
}
VigibotDev commented 4 years ago

Easy blazing fast low latency streaming, faster than the CSI PI camera it's awesome !

ffmpeg hardware encoder on raspberry PI

./capture | ffmpeg -s:v 640x480 -pix_fmt gray -f rawvideo -i pipe: \
                   -c:v h264_omx -profile:v baseline -b:v 1500000 -flags:v +global_header -bsf:v dump_extra \
                   -f rawvideo capture.264

(I output in websocket instead of the 264 raw file)

C code

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include "ASICamera2.h"

#define WIDTH 640
#define HEIGHT 480
#define PIXELCONF ASI_IMG_RAW8
#define PIXELSIZE 1
#define BIN 4
#define EXPOSURE 33
#define GAIN 0

volatile bool run = true;

void signal_callback_handler(int signum) {
 fprintf(stderr, "Caught signal %d\n", signum);
 run = false;
}

int main() {
 if(ASIGetNumOfConnectedCameras() < 1) {
  fprintf(stderr, "Camera not detected\n");
  return 1;
 }

 ASI_CAMERA_INFO *asi_camera_info = (ASI_CAMERA_INFO *) malloc(sizeof(ASI_CAMERA_INFO));
 if(ASIGetCameraProperty(asi_camera_info, 0) == ASI_SUCCESS) {
  fprintf(stderr, "ASI Camera Name: %s\n", asi_camera_info->Name);
  fprintf(stderr, "Camera ID: %d\n", asi_camera_info->CameraID);
  fprintf(stderr, "Width and Height: %d x %d\n", asi_camera_info->MaxWidth, asi_camera_info->MaxHeight);
  fprintf(stderr, "Color: %s\n", asi_camera_info->IsColorCam == ASI_TRUE ? "Yes" : "No");
  fprintf(stderr, "Bayer pattern: %d\n", asi_camera_info->BayerPattern);
  fprintf(stderr, "Pixel size: %1.1f um\n", asi_camera_info->PixelSize);
  fprintf(stderr, "e-/ADU: %1.2f\n", asi_camera_info->ElecPerADU);
  fprintf(stderr, "Bit depth: %d\n", asi_camera_info->BitDepth);
  fprintf(stderr, "Trigger cam: %s\n", asi_camera_info->IsTriggerCam == 0 ? "No" : "Yes");
 } else {
  fprintf(stderr, "Error getting properties of the camera\n");
  return 1;
 }

 int id = asi_camera_info->CameraID;
 if(ASIOpenCamera(id) != ASI_SUCCESS) {
  fprintf(stderr, "Error opening camera\n");
  return 1;
 }

 if(ASIInitCamera(id) != ASI_SUCCESS) {
  fprintf(stderr, "Error initializing camera\n");
  return 1;
 }

 int asi_num_controls = 0;
 if(ASIGetNumOfControls(id, &asi_num_controls) != ASI_SUCCESS) {
  fprintf(stderr, "Error getting number of controls of camera\n");
  return 1;
 }
 ASI_CONTROL_CAPS **asi_control_caps = (ASI_CONTROL_CAPS **) malloc(sizeof(ASI_CONTROL_CAPS *) * asi_num_controls);
 for(int i = 0; i < asi_num_controls; i++) {
  asi_control_caps[i] = (ASI_CONTROL_CAPS *) malloc(sizeof(ASI_CONTROL_CAPS));
  ASIGetControlCaps(id, i, asi_control_caps[i]);
  fprintf(stderr, "%s: [%d, %d] = %d%s - %s\n", asi_control_caps[i]->Name,
                                                asi_control_caps[i]->MinValue,
                                                asi_control_caps[i]->MaxValue,
                                                asi_control_caps[i]->DefaultValue,
                                                asi_control_caps[i]->IsWritable == 1 ? " (set)" : "",
                                                asi_control_caps[i]->Description);
 }

 ASISetROIFormat(id, WIDTH, HEIGHT, BIN, PIXELCONF);

 ASISetControlValue(id, ASI_EXPOSURE, EXPOSURE * 1000, ASI_FALSE);
 ASISetControlValue(id, ASI_GAIN, GAIN, ASI_FALSE);
 ASISetControlValue(id, ASI_BANDWIDTHOVERLOAD, 90, ASI_FALSE);
 ASISetControlValue(id, ASI_HIGH_SPEED_MODE, false, ASI_FALSE);

 signal(SIGINT, signal_callback_handler);
 signal(SIGTERM, signal_callback_handler);

 ASI_EXPOSURE_STATUS asi_exp_status;
 long image_size = WIDTH * HEIGHT * PIXELSIZE;
 unsigned char *asi_image = (unsigned char *) malloc(sizeof(unsigned char) * image_size);

 ASIStartVideoCapture(id);

 while(run) {
  ASIGetVideoData(id, asi_image, image_size, EXPOSURE);
  fwrite(asi_image, image_size, 1, stdout);
 }

 ASICloseCamera(id);
 return 0;
}
bgottula commented 4 years ago

Nice! Glad you were able to figure out something that works for you. I like the integration with ffmpeg for live streaming.

I'll close this out since it looks like there is no action as far as this repository is concerned.