/** @brief Convert a frame from UYVY to BGR * @ingroup frame * @param ini UYVY frame * @param out BGR frame */ uvc_error_t uvc_uyvy2bgr(uvc_frame_t *in, uvc_frame_t *out) { if (in->frame_format != UVC_FRAME_FORMAT_UYVY) return UVC_ERROR_INVALID_PARAM; if (uvc_ensure_frame_size(out, in->width * in->height * 3) < 0) return UVC_ERROR_NO_MEM; out->width = in->width; out->height = in->height; out->frame_format = UVC_FRAME_FORMAT_BGR; out->step = in->width *3; out->sequence = in->sequence; out->capture_time = in->capture_time; out->source = in->source; uint8_t *pyuv = static_cast<uint8_t *>(in->data); uint8_t *pbgr = static_cast<uint8_t *>(out->data); uint8_t *pbgr_end = pbgr + out->data_bytes; while (pbgr < pbgr_end) { IUYVY2BGR_8(pyuv, pbgr); pbgr += 3 * 8; pyuv += 2 * 8; } return UVC_SUCCESS; }
/** @brief Convert a frame from YUYV to UV (GRAY8) * @ingroup frame * * @param in YUYV frame * @param out GRAY8 frame */ uvc_error_t uvc_yuyv2uv(uvc_frame_t *in, uvc_frame_t *out) { if (in->frame_format != UVC_FRAME_FORMAT_YUYV) return UVC_ERROR_INVALID_PARAM; if (uvc_ensure_frame_size(out, in->width * in->height) < 0) return UVC_ERROR_NO_MEM; out->width = in->width; out->height = in->height; out->frame_format = UVC_FRAME_FORMAT_GRAY8; out->step = in->width; out->sequence = in->sequence; out->capture_time = in->capture_time; out->source = in->source; uint8_t *pyuv = static_cast<uint8_t *>(in->data); uint8_t *puv = static_cast<uint8_t *>(out->data); uint8_t *puv_end = puv + out->data_bytes; while (puv < puv_end) { IYUYV2UV(pyuv, puv); puv += 1; pyuv += 2; } return UVC_SUCCESS; }
/** @brief Convert a frame from YUYV to RGB * @ingroup frame * * @param in YUYV frame * @param out RGB frame */ uvc_error_t uvc_yuyv2rgb(uvc_frame_t *in, uvc_frame_t *out) { if (in->frame_format != UVC_FRAME_FORMAT_YUYV) return UVC_ERROR_INVALID_PARAM; if (uvc_ensure_frame_size(out, in->width * in->height * 3) < 0) return UVC_ERROR_NO_MEM; out->width = in->width; out->height = in->height; out->frame_format = UVC_FRAME_FORMAT_RGB; out->step = in->width * 3; out->sequence = in->sequence; out->capture_time = in->capture_time; out->source = in->source; uint8_t *pyuv = static_cast<uint8_t *>(in->data); uint8_t *prgb = static_cast<uint8_t *>(out->data); uint8_t *prgb_end = prgb + out->data_bytes; while (prgb < prgb_end) { IYUYV2RGB_8(pyuv, prgb); prgb += 3 * 8; pyuv += 2 * 8; } return UVC_SUCCESS; }
/** @brief Duplicate a frame, preserving color format * @ingroup frame * * @param in Original frame * @param out Duplicate frame */ uvc_error_t uvc_duplicate_frame(uvc_frame_t *in, uvc_frame_t *out) { if (uvc_ensure_frame_size(out, in->data_bytes) < 0) return UVC_ERROR_NO_MEM; out->width = in->width; out->height = in->height; out->frame_format = in->frame_format; out->step = in->step; out->sequence = in->sequence; out->capture_time = in->capture_time; out->source = in->source; memcpy(out->data, in->data, in->data_bytes); return UVC_SUCCESS; }
void CallbackPipeline::do_capture(JNIEnv *env) { ENTER(); uvc_frame_t *frame; uvc_frame_t *temp = get_frame(default_frame_size); uvc_frame_t *callback_frame; uint32_t width = 0, height = 0; size_t sz = default_frame_size; if (LIKELY(temp)) { for (; isRunning() && isCapturing();) { frame = waitCaptureFrame(); if ((LIKELY(frame))) { if (UNLIKELY((width != frame->width) || (height != frame->height))) { width = frame->width; height = frame->height; callbackPixelFormatChanged(width, height); uvc_ensure_frame_size(temp, callbackPixelBytes); sz = callbackPixelBytes; } if (mFrameCallbackObj) { callback_frame = frame; sz = frame->actual_bytes; if (mFrameCallbackFunc) { callback_frame = temp; sz = callbackPixelBytes; int b = mFrameCallbackFunc(frame, temp); if (UNLIKELY(b)) { LOGW("failed to convert to callback frame"); goto SKIP; } } jobject buf = env->NewDirectByteBuffer(callback_frame->data, callbackPixelBytes); env->CallVoidMethod(mFrameCallbackObj, iframecallback_fields.onFrame, buf); env->ExceptionClear(); env->DeleteLocalRef(buf); } SKIP: recycle_frame(frame); } } recycle_frame(temp); } EXIT(); }
uvc_error_t uvc_mjpeg2yuyv(uvc_frame_t *in, uvc_frame_t *out) { out->actual_bytes = 0; // XXX if (UNLIKELY(in->frame_format != UVC_FRAME_FORMAT_MJPEG)) return UVC_ERROR_INVALID_PARAM; if (uvc_ensure_frame_size(out, in->width * in->height * 2) < 0) return UVC_ERROR_NO_MEM; size_t lines_read = 0; int i, j; int num_scanlines; register uint8_t *yuyv, *ycbcr; out->width = in->width; out->height = in->height; out->frame_format = UVC_FRAME_FORMAT_YUYV; out->step = in->width * 2; out->sequence = in->sequence; out->capture_time = in->capture_time; out->source = in->source; struct jpeg_decompress_struct dinfo; struct error_mgr jerr; dinfo.err = jpeg_std_error(&jerr.super); jerr.super.error_exit = _error_exit; if (setjmp(jerr.jmp)) { goto fail; } jpeg_create_decompress(&dinfo); jpeg_mem_src(&dinfo, in->data, in->actual_bytes/*in->data_bytes*/); // XXX jpeg_read_header(&dinfo, TRUE); if (dinfo.dc_huff_tbl_ptrs[0] == NULL) { /* This frame is missing the Huffman tables: fill in the standard ones */ insert_huff_tables(&dinfo); } dinfo.out_color_space = JCS_YCbCr; dinfo.dct_method = JDCT_IFAST; // start decompressor jpeg_start_decompress(&dinfo); // these dinfo.xxx valiables are only valid after jpeg_start_decompress const int row_stride = dinfo.output_width * dinfo.output_components; // allocate buffer register JSAMPARRAY buffer = (*dinfo.mem->alloc_sarray) ((j_common_ptr) &dinfo, JPOOL_IMAGE, row_stride, MAX_READLINE); // local copy uint8_t *data = out->data; const int out_step = out->step; if (LIKELY(dinfo.output_height == out->height)) { for (; dinfo.output_scanline < dinfo.output_height ;) { // convert lines of mjpeg data to YCbCr num_scanlines = jpeg_read_scanlines(&dinfo, buffer, MAX_READLINE); // convert YCbCr to yuyv(YUV422) for (j = 0; j < num_scanlines; j++) { yuyv = data + (lines_read + j) * out_step; ycbcr = buffer[j]; for (i = 0; i < row_stride; i += 24) { // step by YCbCr x 8 pixels = 3 x 8 bytes YCbCr_YUYV_2(ycbcr + i, yuyv); YCbCr_YUYV_2(ycbcr + i + 6, yuyv); YCbCr_YUYV_2(ycbcr + i + 12, yuyv); YCbCr_YUYV_2(ycbcr + i + 18, yuyv); } } lines_read += num_scanlines; } out->actual_bytes = in->width * in->height * 2; // XXX } jpeg_finish_decompress(&dinfo); jpeg_destroy_decompress(&dinfo); return lines_read == out->height ? UVC_SUCCESS : UVC_ERROR_OTHER; fail: jpeg_destroy_decompress(&dinfo); return lines_read == out->height ? UVC_SUCCESS : UVC_ERROR_OTHER+1; }
/** @brief Convert an MJPEG frame to RGB * @ingroup frame * * @param in MJPEG frame * @param out RGB frame */ uvc_error_t uvc_mjpeg2rgb(uvc_frame_t *in, uvc_frame_t *out) { struct jpeg_decompress_struct dinfo; struct error_mgr jerr; size_t lines_read; // local copy uint8_t *data = out->data; const int out_step = out->step; int num_scanlines, i; lines_read = 0; unsigned char *buffer[MAX_READLINE]; out->actual_bytes = 0; // XXX if (UNLIKELY(in->frame_format != UVC_FRAME_FORMAT_MJPEG)) return UVC_ERROR_INVALID_PARAM; if (uvc_ensure_frame_size(out, in->width * in->height * 3) < 0) return UVC_ERROR_NO_MEM; out->width = in->width; out->height = in->height; out->frame_format = UVC_FRAME_FORMAT_RGB; out->step = in->width * 3; out->sequence = in->sequence; out->capture_time = in->capture_time; out->source = in->source; dinfo.err = jpeg_std_error(&jerr.super); jerr.super.error_exit = _error_exit; if (setjmp(jerr.jmp)) { goto fail; } jpeg_create_decompress(&dinfo); jpeg_mem_src(&dinfo, in->data, in->actual_bytes/*in->data_bytes*/); jpeg_read_header(&dinfo, TRUE); if (dinfo.dc_huff_tbl_ptrs[0] == NULL) { /* This frame is missing the Huffman tables: fill in the standard ones */ insert_huff_tables(&dinfo); } dinfo.out_color_space = JCS_RGB; dinfo.dct_method = JDCT_IFAST; jpeg_start_decompress(&dinfo); if (LIKELY(dinfo.output_height == out->height)) { for (; dinfo.output_scanline < dinfo.output_height ;) { buffer[0] = data + (lines_read) * out_step; for (i = 1; i < MAX_READLINE; i++) buffer[i] = buffer[i-1] + out_step; num_scanlines = jpeg_read_scanlines(&dinfo, buffer, MAX_READLINE); lines_read += num_scanlines; } out->actual_bytes = in->width * in->height * 3; // XXX } jpeg_finish_decompress(&dinfo); jpeg_destroy_decompress(&dinfo); return lines_read == out->height ? UVC_SUCCESS : UVC_ERROR_OTHER; // XXX fail: jpeg_destroy_decompress(&dinfo); return UVC_ERROR_OTHER+1; }