int camera_device_stop_capturing(CameraDevice* cd) { WndCameraDevice* wcd; if (cd == NULL || cd->opaque == NULL) { E("%s: Invalid camera device descriptor", __FUNCTION__); return -1; } wcd = (WndCameraDevice*)cd->opaque; /* Disable frame callback. */ capSetCallbackOnFrame(wcd->cap_window, NULL); /* wcd->dc is the indicator of capture. */ if (wcd->dc == NULL) { W("%s: Device '%s' is not capturing video", __FUNCTION__, wcd->window_name); return 0; } ReleaseDC(wcd->cap_window, wcd->dc); wcd->dc = NULL; /* Reset the device in preparation for the next capture. */ _camera_device_reset(wcd); return 0; }
int camera_device_stop_capturing(CameraDevice* ccd) { enum v4l2_buf_type type; LinuxCameraDevice* cd; /* Sanity checks. */ if (ccd == NULL || ccd->opaque == NULL) { E("%s: Invalid camera device descriptor", __FUNCTION__); return -1; } cd = (LinuxCameraDevice*)ccd->opaque; if (cd->handle < 0) { E("%s: Camera device is not opened", __FUNCTION__); return -1; } switch (cd->io_type) { case CAMERA_IO_DIRECT: /* Nothing to do. */ break; case CAMERA_IO_MEMMAP: case CAMERA_IO_USERPTR: type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (_xioctl(cd->handle, VIDIOC_STREAMOFF, &type) < 0) { E("%s: VIDIOC_STREAMOFF on camera '%s' has failed: %s", __FUNCTION__, cd->device_name, strerror(errno)); return -1; } break; default: E("%s: Unknown I/O method: %d", __FUNCTION__, cd->io_type); return -1; } /* Reopen the device to reset its internal state. It seems that if we don't * do that, an attempt to reinit the device with different frame dimensions * would fail. */ _camera_device_reset(cd); return 0; }
int camera_device_start_capturing(CameraDevice* cd, uint32_t pixel_format, int frame_width, int frame_height) { WndCameraDevice* wcd; HBITMAP bm_handle; BITMAP bitmap; size_t format_info_size; if (cd == NULL || cd->opaque == NULL) { E("%s: Invalid camera device descriptor", __FUNCTION__); return -1; } wcd = (WndCameraDevice*)cd->opaque; /* wcd->dc is an indicator of capturing: !NULL - capturing, NULL - not */ if (wcd->dc != NULL) { W("%s: Capturing is already on on device '%s'", __FUNCTION__, wcd->window_name); return 0; } /* Connect capture window to the video capture driver. */ if (!capDriverConnect(wcd->cap_window, wcd->input_channel)) { return -1; } /* Get current frame information from the driver. */ format_info_size = capGetVideoFormatSize(wcd->cap_window); if (format_info_size == 0) { E("%s: Unable to get video format size: %d", __FUNCTION__, GetLastError()); _camera_device_reset(wcd); return -1; } wcd->frame_bitmap = (BITMAPINFO*)malloc(format_info_size); if (wcd->frame_bitmap == NULL) { E("%s: Unable to allocate frame bitmap info buffer", __FUNCTION__); _camera_device_reset(wcd); return -1; } if (!capGetVideoFormat(wcd->cap_window, wcd->frame_bitmap, format_info_size)) { E("%s: Unable to obtain video format: %d", __FUNCTION__, GetLastError()); _camera_device_reset(wcd); return -1; } /* Lets see if we need to set different frame dimensions */ if (wcd->frame_bitmap->bmiHeader.biWidth != frame_width || abs(wcd->frame_bitmap->bmiHeader.biHeight) != frame_height) { /* Dimensions don't match. Set new frame info. */ wcd->frame_bitmap->bmiHeader.biWidth = frame_width; wcd->frame_bitmap->bmiHeader.biHeight = frame_height; /* We need to recalculate image size, since the capture window / driver * will use image size provided by us. */ if (wcd->frame_bitmap->bmiHeader.biBitCount == 24) { /* Special case that may require WORD boundary alignment. */ uint32_t bpl = (frame_width * 3 + 1) & ~1; wcd->frame_bitmap->bmiHeader.biSizeImage = bpl * frame_height; } else { wcd->frame_bitmap->bmiHeader.biSizeImage = (frame_width * frame_height * wcd->frame_bitmap->bmiHeader.biBitCount) / 8; } if (!capSetVideoFormat(wcd->cap_window, wcd->frame_bitmap, format_info_size)) { E("%s: Unable to set video format: %d", __FUNCTION__, GetLastError()); _camera_device_reset(wcd); return -1; } } if (wcd->frame_bitmap->bmiHeader.biCompression > BI_PNG) { D("%s: Video capturing driver has reported pixel format %.4s", __FUNCTION__, (const char*)&wcd->frame_bitmap->bmiHeader.biCompression); } /* Most of the time frame bitmaps come in "bottom-up" form, where its origin * is the lower-left corner. However, it could be in the normal "top-down" * form with the origin in the upper-left corner. So, we must adjust the * biHeight field, since the way "top-down" form is reported here is by * setting biHeight to a negative value. */ if (wcd->frame_bitmap->bmiHeader.biHeight < 0) { wcd->frame_bitmap->bmiHeader.biHeight = -wcd->frame_bitmap->bmiHeader.biHeight; wcd->is_top_down = 1; } else { wcd->is_top_down = 0; } /* Get DC for the capturing window that will be used when we deal with * bitmaps obtained from the camera device during frame capturing. */ wcd->dc = GetDC(wcd->cap_window); if (wcd->dc == NULL) { E("%s: Unable to obtain DC for %s: %d", __FUNCTION__, wcd->window_name, GetLastError()); _camera_device_reset(wcd); return -1; } /* * At this point we need to grab a frame to properly setup framebuffer, and * calculate pixel format. The problem is that bitmap information obtained * from the driver doesn't necessarily match the actual bitmap we're going to * obtain via capGrabFrame / capEditCopy / GetClipboardData */ /* Grab a frame, and post it to the clipboard. Not very effective, but this * is how capXxx API is operating. */ if (!capGrabFrameNoStop(wcd->cap_window) || !capEditCopy(wcd->cap_window) || !OpenClipboard(wcd->cap_window)) { E("%s: Device '%s' is unable to save frame to the clipboard: %d", __FUNCTION__, wcd->window_name, GetLastError()); _camera_device_reset(wcd); return -1; } /* Get bitmap handle saved into clipboard. Note that bitmap is still * owned by the clipboard here! */ bm_handle = (HBITMAP)GetClipboardData(CF_BITMAP); if (bm_handle == NULL) { E("%s: Device '%s' is unable to obtain frame from the clipboard: %d", __FUNCTION__, wcd->window_name, GetLastError()); CloseClipboard(); _camera_device_reset(wcd); return -1; } /* Get bitmap object that is initialized with the actual bitmap info. */ if (!GetObject(bm_handle, sizeof(BITMAP), &bitmap)) { E("%s: Device '%s' is unable to obtain frame's bitmap: %d", __FUNCTION__, wcd->window_name, GetLastError()); CloseClipboard(); _camera_device_reset(wcd); return -1; } /* Now that we have all we need in 'bitmap' */ CloseClipboard(); /* Make sure that dimensions match. Othewise - fail. */ if (wcd->frame_bitmap->bmiHeader.biWidth != bitmap.bmWidth || wcd->frame_bitmap->bmiHeader.biHeight != bitmap.bmHeight ) { E("%s: Requested dimensions %dx%d do not match the actual %dx%d", __FUNCTION__, frame_width, frame_height, wcd->frame_bitmap->bmiHeader.biWidth, wcd->frame_bitmap->bmiHeader.biHeight); _camera_device_reset(wcd); return -1; } /* Create bitmap info that will be used with GetDIBits. */ wcd->gdi_bitmap = (BITMAPINFO*)malloc(wcd->frame_bitmap->bmiHeader.biSize); if (wcd->gdi_bitmap == NULL) { E("%s: Unable to allocate gdi bitmap info", __FUNCTION__); _camera_device_reset(wcd); return -1; } memcpy(wcd->gdi_bitmap, wcd->frame_bitmap, wcd->frame_bitmap->bmiHeader.biSize); wcd->gdi_bitmap->bmiHeader.biCompression = BI_RGB; wcd->gdi_bitmap->bmiHeader.biBitCount = bitmap.bmBitsPixel; wcd->gdi_bitmap->bmiHeader.biSizeImage = bitmap.bmWidthBytes * bitmap.bmWidth; /* Adjust GDI's bitmap biHeight for proper frame direction ("top-down", or * "bottom-up") We do this trick in order to simplify pixel format conversion * routines, where we always assume "top-down" frames. The trick he is to * have negative biHeight in 'gdi_bitmap' if driver provides "bottom-up" * frames, and positive biHeight in 'gdi_bitmap' if driver provides "top-down" * frames. This way GetGDIBits will always return "top-down" frames. */ if (wcd->is_top_down) { wcd->gdi_bitmap->bmiHeader.biHeight = wcd->frame_bitmap->bmiHeader.biHeight; } else { wcd->gdi_bitmap->bmiHeader.biHeight = -wcd->frame_bitmap->bmiHeader.biHeight; } /* Allocate framebuffer. */ wcd->framebuffer = (uint8_t*)malloc(wcd->gdi_bitmap->bmiHeader.biSizeImage); if (wcd->framebuffer == NULL) { E("%s: Unable to allocate %d bytes for framebuffer", __FUNCTION__, wcd->gdi_bitmap->bmiHeader.biSizeImage); _camera_device_reset(wcd); return -1; } /* Lets see what pixel format we will use. */ if (wcd->gdi_bitmap->bmiHeader.biBitCount == 16) { wcd->pixel_format = V4L2_PIX_FMT_RGB565; } else if (wcd->gdi_bitmap->bmiHeader.biBitCount == 24) { wcd->pixel_format = V4L2_PIX_FMT_BGR24; } else if (wcd->gdi_bitmap->bmiHeader.biBitCount == 32) { wcd->pixel_format = V4L2_PIX_FMT_BGR32; } else { E("%s: Unsupported number of bits per pixel %d", __FUNCTION__, wcd->gdi_bitmap->bmiHeader.biBitCount); _camera_device_reset(wcd); return -1; } D("%s: Capturing device '%s': %d bits per pixel in %.4s [%dx%d] frame", __FUNCTION__, wcd->window_name, wcd->gdi_bitmap->bmiHeader.biBitCount, (const char*)&wcd->pixel_format, wcd->frame_bitmap->bmiHeader.biWidth, wcd->frame_bitmap->bmiHeader.biHeight); return 0; }
int camera_device_start_capturing(CameraDevice* ccd, uint32_t pixel_format, int frame_width, int frame_height) { struct v4l2_format fmt; LinuxCameraDevice* cd; char fmt_str[5]; int r; int log = 0; printf("This is :::: %d\n", log++);//obiah 0 /* Sanity checks. */ if (ccd == NULL || ccd->opaque == NULL) { E("%s: Invalid camera device descriptor", __FUNCTION__); return -1; } printf("This is :::: %d\n", log++);//obiah 1 cd = (LinuxCameraDevice*)ccd->opaque; if (cd->handle < 0) { E("%s: Camera device is not opened", __FUNCTION__); return -1; } printf("This is :::: %d\n", log++);//obiah 2 /* Try to set pixel format with the given dimensions. */ CLEAR(fmt); fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmt.fmt.pix.width = frame_width; fmt.fmt.pix.height = frame_height; fmt.fmt.pix.pixelformat = pixel_format; if (_xioctl(cd->handle, VIDIOC_S_FMT, &fmt) < 0) { memcpy(fmt_str, &pixel_format, 4); fmt_str[4] = '\0'; E("%s: Camera '%s' does not support pixel format '%s' with dimensions %dx%d", __FUNCTION__, cd->device_name, fmt_str, frame_width, frame_height); _camera_device_reset(cd); return -1; } printf("This is :::: %d\n", log++);//obiah 3 /* VIDIOC_S_FMT may has changed some properties of the structure. Make sure * that dimensions didn't change. */ if (fmt.fmt.pix.width != frame_width || fmt.fmt.pix.height != frame_height) { memcpy(fmt_str, &pixel_format, 4); fmt_str[4] = '\0'; E("%s: Dimensions %dx%d are wrong for pixel format '%s'", __FUNCTION__, frame_width, frame_height, fmt_str); _camera_device_reset(cd); return -1; } memcpy(&cd->actual_pixel_format, &fmt.fmt.pix, sizeof(struct v4l2_pix_format)); printf("This is :::: %d\n", log++);//obiah 4 /* * Lets initialize frame buffers, and see what kind of I/O we're going to * use to retrieve frames. */ /* First, lets see if we can do mapped I/O (as most performant one). */ r = _camera_device_mmap_framebuffer(cd); printf("This is :::: %d\n", log++);//obiah 5 if (r < 0) { /* Some critical error has ocurred. Bail out. */ printf("mmap critical error\n");// _camera_device_reset(cd); printf("This is mmap :::: %d\n", log++);//obiah 5 return -1; } else if (r > 0) { /* Device doesn't support memory mapping. Retrieve to the next performant * one: preallocated user buffers. */ r = _camera_device_user_framebuffer(cd); if (r < 0) { printf("user critical error\n");// /* Some critical error has ocurred. Bail out. */ _camera_device_reset(cd); printf("This is user :::: %d\n", log++);//obiah 5 return -1; } else if (r > 0) { /* The only thing left for us is direct reading from the device. */ if (!(cd->caps.capabilities & V4L2_CAP_READWRITE)) { E("%s: Don't know how to access frames on device '%s'", __FUNCTION__, cd->device_name); _camera_device_reset(cd); printf("This is dont know frames:::: %d\n", log++);//obiah return -1; } r = _camera_device_direct_framebuffer(cd); if (r != 0) { /* Any error at this point is a critical one. */ printf("unknown critical error\n");// _camera_device_reset(cd); printf("This is unknown :::: %d\n", log++);//obiah return -1; } } } /* Start capturing from the device. */ if (cd->io_type != CAMERA_IO_DIRECT) { enum v4l2_buf_type type; type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (_xioctl (cd->handle, VIDIOC_STREAMON, &type) < 0) { E("%s: VIDIOC_STREAMON on camera '%s' has failed: %s", __FUNCTION__, cd->device_name, strerror(errno)); _camera_device_reset(cd); printf("This is io direct:::: %d\n", log++);//obiah 5 return -1; } } printf("This is okay!!!:::: %d\n", log++);//obiah 5 return 0; }