diff --git a/ChangeLog b/ChangeLog index 56149bc..a7db038 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2022-11-03: +- fixed: grabbing frame from SVBONY cam is not blocking other threads. +- fixed: converting input pixelformat correctly. Finshed implementing + pixelformat V4L2_PIX_FMT_RGB24 and V4L2_PIX_FMT_BGR24 + 2022-10-30: - fixing many bugs check change log. controls are back working, automatic format detection. diff --git a/convert.cc b/convert.cc index c4a0a42..e6d2472 100644 --- a/convert.cc +++ b/convert.cc @@ -160,6 +160,57 @@ int Convert (ConvertData *cdata, VideoFrame *dest, unsigned char *ptrsrc, int sr yd++; } break; + case (V4L2_PIX_FMT_RGB24): + for (ys = 0, yd = 0; ys < (signed int)srch; ys++) { + for (xs = 0, xd = 0; xs < (signed int)srcw; xs++) { + /* read the pixel */ + + r = *(ptrsrc++); + g = *(ptrsrc++); + b = *(ptrsrc++); + + /* only paint the image if the source is within the destination */ + if (xd < dest->w) { + /* set the pixel */ + *(ptrdst++) = b; + *(ptrdst++) = g; + *(ptrdst++) = r; + xd++; + } + } + + /* if the source image is too small ignore the other places.. */ + if (xd < dest->w) + ptrdst += 3 * (dest->w - xd); + yd++; + } + break; + + case (V4L2_PIX_FMT_BGR24): + for (ys = 0, yd = 0; ys < (signed int)srch; ys++) { + for (xs = 0, xd = 0; xs < (signed int)srcw; xs++) { + /* read the pixel */ + + b = *(ptrsrc++); + g = *(ptrsrc++); + r = *(ptrsrc++); + + /* only paint the image if the source is within the destination */ + if (xd < dest->w) { + /* set the pixel */ + *(ptrdst++) = b; + *(ptrdst++) = g; + *(ptrdst++) = r; + xd++; + } + } + + /* if the source image is too small ignore the other places.. */ + if (xd < dest->w) + ptrdst += 3 * (dest->w - xd); + yd++; + } + break; case (V4L2_PIX_FMT_UYVY): for (ys = 0, yd = 0; ys < (signed int)srch; ys++) { diff --git a/videodev-svbcam.cc b/videodev-svbcam.cc index de8f71e..444ef30 100644 --- a/videodev-svbcam.cc +++ b/videodev-svbcam.cc @@ -15,6 +15,11 @@ VideoDev_SVBCam::VideoDev_SVBCam() { printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); + inframe = NULL; + inframe_size = 0; + inframe_pixfmt = 0; + inframe_w = 0; + inframe_h = 0; camid = -1; }; @@ -196,7 +201,8 @@ int VideoDev_SVBCam::Open() { return VDEV_STATUS_ERROR; } - switch (convert_to_pixelformat(conf_format)) { + inframe_pixfmt = convert_to_pixelformat(conf_format); + switch (inframe_pixfmt) { case (V4L2_PIX_FMT_RGB32): if ((err = SVBSetOutputImageType(camid, SVB_IMG_RGB32)) != SVB_SUCCESS) { print_error(err); @@ -210,7 +216,8 @@ int VideoDev_SVBCam::Open() { } break; default: - conf_format = convert_from_pixelformat(V4L2_PIX_FMT_RGB24); + conf_format = convert_from_pixelformat(V4L2_PIX_FMT_RGB24); + inframe_pixfmt = V4L2_PIX_FMT_RGB24; if ((err = SVBSetOutputImageType(camid, SVB_IMG_RGB24)) != SVB_SUCCESS) { print_error(err); return VDEV_STATUS_ERROR; @@ -221,9 +228,8 @@ int VideoDev_SVBCam::Open() { // // preprare buffer - LockMutex(); - threaddata.vf.SetSize(camprop.MaxWidth, camprop.MaxHeight); - UnLockMutex(); + conf_width = inframe_w = camprop.MaxWidth; + conf_height = inframe_h = camprop.MaxHeight; return VDEV_STATUS_OK; }; @@ -252,6 +258,8 @@ int VideoDev_SVBCam::Close() { /* + * prepare inframe for raw picture data, will hold a video frame with 16bit per channel + * inframe size = 2*3*W*H * send the start capture signal to the cam */ int VideoDev_SVBCam::CaptureStart() { @@ -264,10 +272,21 @@ int VideoDev_SVBCam::CaptureStart() { return VDEV_STATUS_ERROR; } + // + // allocate memory for frame data + if (inframe != NULL) free (inframe); + inframe_size = 6 * inframe_w * inframe_h; + inframe = (unsigned char*) malloc(inframe_size); + + ConvertStart(&cdata, inframe_pixfmt); + return VDEV_STATUS_OK; }; +/* + * free inbuffer + */ int VideoDev_SVBCam::CaptureStop() { int err; @@ -277,6 +296,15 @@ int VideoDev_SVBCam::CaptureStop() { return VDEV_STATUS_ERROR; } + // + // free inframe memory + if (inframe) { + free (inframe); + inframe_size = 0; + } + + ConvertStop(&cdata, inframe_pixfmt); + return VDEV_STATUS_OK; }; @@ -290,14 +318,16 @@ int VideoDev_SVBCam::CaptureStop() { int VideoDev_SVBCam::Grab(VideoFrame *vf) { int err; - LockMutex(); - if ((err = SVBGetVideoData(camid, threaddata.vf.data, (long)threaddata.vf.size, 50)) != SVB_SUCCESS) { + if (inframe == NULL) return VDEV_STATUS_ERROR; + if ((err = SVBGetVideoData(camid, inframe, (long)inframe_size, 50)) != SVB_SUCCESS) { if (err != SVB_ERROR_TIMEOUT) { print_error(err); UnLockMutex(); return VDEV_STATUS_ERROR; } } + LockMutex(); + Convert(&cdata, vf, inframe, inframe_size, inframe_pixfmt, inframe_w, inframe_h); UnLockMutex(); return VDEV_STATUS_OK; diff --git a/videodev-svbcam.h b/videodev-svbcam.h index 77e5784..47b62ad 100644 --- a/videodev-svbcam.h +++ b/videodev-svbcam.h @@ -29,7 +29,10 @@ class VideoDev_SVBCam: public VideoDev { private: - VideoFrame vf; + unsigned char *inframe; + int inframe_size; + int inframe_w, inframe_h; + int inframe_pixfmt; ConvertData cdata; int camid; diff --git a/videodev.cc b/videodev.cc index 34b3f40..bff70d6 100644 --- a/videodev.cc +++ b/videodev.cc @@ -165,9 +165,9 @@ void VideoDev::ThreadProcess() { } threaddata.running = 1; // prevent reading all controlls every time. - // will be set to 2 in callback function + // will be set to 2 in callback function, after the first frame + // is read and all controls a loaded. if (callback) gdk_threads_add_idle(callback, &threaddata); -// threaddata.running = 2; while (running) { i = Grab(&threaddata.vf);