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;
}