Android打开外置UVC相机代替硬件相机

时间:2016-06-15 07:09:08

标签: android android-camera

我需要用

打开外置UVC相机

Camera.open(CameraId);

但没有工作

请帮帮忙?

5 个答案:

答案 0 :(得分:3)

不幸的是,虽然camera2 API确实拥有必要的API接口来支持外部摄像头,例如USB网络摄像头,但对外部摄像头还没有标准的低级支持。

某些设备制造商确实有这样的支持,但目前只有极少数设备。

在此之前,Android应用程序可以使用USB网络摄像头的唯一方法是直接使用原始USB API,而根本不使用相机API。您可以尝试查找要使用的现有UVC库,也可以编写自己的。

答案 1 :(得分:2)

我正在研究这个主题好几天,并将在这里贡献我的部分发现。

  1. 有一个本机库可用于访问外部UVC摄像机https://github.com/ktossell/libuvc。我发现这个项目使用了它,当我编译和测试它时,我发现样本只是部分稳定,而且它的源代码压倒性。
  2. 2年前的Camera2 API似乎包括外部相机支持。我在Android project documentation - Camera device中发现了以下陈述:
      

    "外部摄像头(例如USB热插拔摄像头)支持。 API更新指定摄像机静态信息仅在摄像机已连接且可以用于外部热插拔摄像机时可用。当摄像机状态不是CAMERA_DEVICE_STATUS_PRESENT时,调用获取静态信息将是无效呼叫。该框架仅依靠设备状态更改回调来管理可用的外部摄像机列表。"

  3. 我无法使用访问我的网络摄像头的Camera2 API编写代码。

    最后,我甚至在Android source code中找到了以下代码

      

    (144)// TODO:合并HAL API更改后更新为CAMERA_FACING_EXTERNAL。

    虽然CAMERA_FACING_EXTERNAL对于外置摄像头来说是CameraInfo class的新值,但显然不是FRONT而是没有回来。

    我希望这会帮助你朝着完整的答案前进。

答案 2 :(得分:2)

AOSP包含使用V4L2的Camera3 HAL实现。它甚至附带了一个很好的自述文件,也指出了它目前的局限性: https://github.com/aosp-mirror/platform_hardware_libhardware/tree/master/modules/camera/3_4

答案 3 :(得分:0)

此功能已在某些平台上实现,方法是将硬件上camera_device_ops_t中的每个功能重定位到USB_CAMERA功能,如下所示:

camera_device_ops_t usb_camera_camera_ops = {
  set_preview_window:         usb_camera_set_preview_window,
  set_callbacks:              usb_camera_set_CallBacks,
  enable_msg_type:            usb_camera_enable_msg_type,
  disable_msg_type:           usb_camera_disable_msg_type,
  msg_type_enabled:           usb_camera_msg_type_enabled,

  start_preview:              usb_camera_start_preview,
  stop_preview:               usb_camera_stop_preview,
  preview_enabled:            usb_camera_preview_enabled,
  store_meta_data_in_buffers: usb_camera_store_meta_data_in_buffers,

  start_recording:            usb_camera_start_recording,
  stop_recording:             usb_camera_stop_recording,
  recording_enabled:          usb_camera_recording_enabled,
  release_recording_frame:    usb_camera_release_recording_frame,

  auto_focus:                 usb_camera_auto_focus,
  cancel_auto_focus:          usb_camera_cancel_auto_focus,

  take_picture:               usb_camera_take_picture,
  cancel_picture:             usb_camera_cancel_picture,

  set_parameters:             usb_camera_set_parameters,
  get_parameters:             usb_camera_get_parameters,
  put_parameters:             usb_camera_put_parameters,
  send_command:               usb_camera_send_command,

  release:                    usb_camera_release,
  dump:                       usb_camera_dump,
};

答案 4 :(得分:0)

USB相机无法在较新的camera2 API上运行。较旧的camera2 API可能支持USB摄像头

但是,只要有适当的支持,USB摄像头就可以在camera1 api上运行。 在界面3.4中,我还启用了YUV支持。

这是我的全部作品

UVC Camera support in AOSP

这是camera/device/3.4/default/ExternalCameraDevice.cpp YUV支持的补丁程序

diff --git a/camera/device/3.4/default/ExternalCameraDevice.cpp b/camera/device/3.4/default/ExternalCameraDevice.cpp
index ee7ffaa..2444404 100644
--- a/camera/device/3.4/default/ExternalCameraDevice.cpp
+++ b/camera/device/3.4/default/ExternalCameraDevice.cpp
@@ -38,8 +38,10 @@ namespace {
 // Other formats to consider in the future:
 // * V4L2_PIX_FMT_YVU420 (== YV12)
 // * V4L2_PIX_FMT_YVYU (YVYU: can be converted to YV12 or other YUV420_888 formats)
-const std::array<uint32_t, /*size*/1> kSupportedFourCCs {{
-    V4L2_PIX_FMT_MJPEG
+const std::array<uint32_t, /*size*/3> kSupportedFourCCs {{
+    V4L2_PIX_FMT_MJPEG,
+    V4L2_PIX_FMT_YUYV,
+    V4L2_PIX_FMT_YUV420
 }}; // double braces required in C++11
 
 constexpr int MAX_RETRY = 5; // Allow retry v4l2 open failures a few times.
diff --git a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
index 1af3f39..37bf75f 100644
--- a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
+++ b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
@@ -1724,33 +1724,60 @@ bool ExternalCameraDeviceSession::OutputThread::threadLoop() {
         return false;
     };
 
-    if (req->frameIn->mFourcc != V4L2_PIX_FMT_MJPEG) {
-        return onDeviceError("%s: do not support V4L2 format %c%c%c%c", __FUNCTION__,
+    if (req->frameIn->mFourcc != V4L2_PIX_FMT_MJPEG && req->frameIn->mFourcc != V4L2_PIX_FMT_YUYV && req->frameIn->mFourcc != V4L2_PIX_FMT_YUV420) {
+        return onDeviceError("%s: do not support V4L2 format %c%c%c%c xxx", __FUNCTION__,
                 req->frameIn->mFourcc & 0xFF,
                 (req->frameIn->mFourcc >> 8) & 0xFF,
                 (req->frameIn->mFourcc >> 16) & 0xFF,
                 (req->frameIn->mFourcc >> 24) & 0xFF);
     }
+    ALOGV("%s: V4L2 format: %c%c%c%c", __FUNCTION__,
+                req->frameIn->mFourcc & 0xFF,
+                (req->frameIn->mFourcc >> 8) & 0xFF,
+                (req->frameIn->mFourcc >> 16) & 0xFF,
+                (req->frameIn->mFourcc >> 24) & 0xFF);
 
     std::unique_lock<std::mutex> lk(mBufferLock);
     // Convert input V4L2 frame to YU12 of the same size
     // TODO: see if we can save some computation by converting to YV12 here
     uint8_t* inData;
     size_t inDataSize;
+    int res = -1;
     req->frameIn->map(&inData, &inDataSize);
-    // TODO: in some special case maybe we can decode jpg directly to gralloc output?
-    ATRACE_BEGIN("MJPGtoI420");
-    int res = libyuv::MJPGToI420(
-            inData, inDataSize,
-            static_cast<uint8_t*>(mYu12FrameLayout.y),
-            mYu12FrameLayout.yStride,
-            static_cast<uint8_t*>(mYu12FrameLayout.cb),
-            mYu12FrameLayout.cStride,
-            static_cast<uint8_t*>(mYu12FrameLayout.cr),
-            mYu12FrameLayout.cStride,
-            mYu12Frame->mWidth, mYu12Frame->mHeight,
-            mYu12Frame->mWidth, mYu12Frame->mHeight);
-    ATRACE_END();
+    ALOGV("%s: Size: %zu, WxH: (%u, %u)", __FUNCTION__, inDataSize, mYu12Frame->mWidth, mYu12Frame->mHeight);
+    if (req->frameIn->mFourcc == V4L2_PIX_FMT_MJPEG) {
+        // TODO: in some special case maybe we can decode jpg directly to gralloc output?
+        ATRACE_BEGIN("MJPGtoI420");
+        res = libyuv::MJPGToI420(
+                inData, inDataSize,
+                static_cast<uint8_t*>(mYu12FrameLayout.y),
+                mYu12FrameLayout.yStride,
+                static_cast<uint8_t*>(mYu12FrameLayout.cb),
+                mYu12FrameLayout.cStride,
+                static_cast<uint8_t*>(mYu12FrameLayout.cr),
+                mYu12FrameLayout.cStride,
+                mYu12Frame->mWidth, mYu12Frame->mHeight,
+                mYu12Frame->mWidth, mYu12Frame->mHeight);
+        ATRACE_END();
+    } else if (req->frameIn->mFourcc == V4L2_PIX_FMT_YUYV && inDataSize != libyuv::kUnknownDataSize ) { //&& inDataSize != libyuv::kUnknownDataSize
+        ALOGV("%s: Converting to I420 | Size: %zu, WxH: (%ux%u), yStride: %u, cStride: %u", __FUNCTION__, inDataSize, mYu12Frame->mWidth, mYu12Frame->mHeight, mYu12FrameLayout.yStride, mYu12FrameLayout.cStride);
+        ATRACE_BEGIN("YUY2ToI420");
+        res = libyuv::YUY2ToI420(inData, mYu12Frame->mWidth * 2,
+                static_cast<uint8_t*>(mYu12FrameLayout.y),
+                mYu12FrameLayout.yStride,
+                static_cast<uint8_t*>(mYu12FrameLayout.cb),
+                mYu12FrameLayout.cStride,
+                static_cast<uint8_t*>(mYu12FrameLayout.cr),
+                mYu12FrameLayout.cStride,
+                mYu12Frame->mWidth, mYu12Frame->mHeight);
+        ATRACE_END();
+    } else{
+        ALOGV("%s: YUV420 format. No conversion", __FUNCTION__);
+        memcpy(static_cast<uint8_t*>(mYu12FrameLayout.y), inData, inDataSize/2);
+        memcpy(static_cast<uint8_t*>(mYu12FrameLayout.cb), (inData + inDataSize/2), inDataSize/4);
+        memcpy(static_cast<uint8_t*>(mYu12FrameLayout.cr), (inData + inDataSize/2 + inDataSize/4), inDataSize/4 );
+        res = 0;
+    }
 
     if (res != 0) {
         // For some webcam, the first few V4L2 frames might be malformed...

/hardware/qcom/camera的另一个差异


diff --git a/QCamera2/HAL/QCameraParameters.cpp b/QCamera2/HAL/QCameraParameters.cpp
index 90d83d0..293229b 100644
--- a/QCamera2/HAL/QCameraParameters.cpp
+++ b/QCamera2/HAL/QCameraParameters.cpp
@@ -11675,7 +11675,7 @@ uint32_t QCameraParameters::getJpegQuality()
 {
     int quality = getInt(KEY_JPEG_QUALITY);
     if (quality < 0) {
-        quality = 85; // set to default quality value
+        quality = 90; // set to default quality value
     }
     return (uint32_t)quality;
 }
@@ -11691,7 +11691,7 @@ uint32_t QCameraParameters::getJpegQuality()
  *==========================================================================*/
 uint32_t QCameraParameters::getRotation() {
     int rotation = 0;
-
+    LOGE("%s: %d", __func__, mRotation);
     //If exif rotation is set, do not rotate captured image
     if (!useJpegExifRotation()) {
         rotation = mRotation;
@@ -11729,7 +11729,7 @@ void QCameraParameters::setJpegRotation(int rotation) {
  *==========================================================================*/
 uint32_t QCameraParameters::getDeviceRotation() {
     int rotation = 0;
-
+    LOGE("%s: %d", __func__, mRotation);
     rotation = mRotation;
     if (rotation < 0) {
         rotation = 0;
@@ -11749,7 +11749,7 @@ uint32_t QCameraParameters::getDeviceRotation() {
  *==========================================================================*/
 uint32_t QCameraParameters::getJpegExifRotation() {
     int rotation = 0;
-
+    LOGE("%s: %d", __func__, mRotation);
     if (useJpegExifRotation()) {
         rotation = mRotation;
         if (rotation < 0) {
@@ -11772,7 +11772,7 @@ bool QCameraParameters::useJpegExifRotation() {
     char exifRotation[PROPERTY_VALUE_MAX];
 
     property_get("persist.vendor.camera.exif.rotation", exifRotation, "off");
-
+    LOGE("%s: %s", __func__, exifRotation);
     if (!strcmp(exifRotation, "on")) {
         return true;
     }
diff --git a/usbcamcore/inc/QCameraUsbParm.h b/usbcamcore/inc/QCameraUsbParm.h
index 595bf42..9e1e070 100755
--- a/usbcamcore/inc/QCameraUsbParm.h
+++ b/usbcamcore/inc/QCameraUsbParm.h
@@ -62,13 +62,13 @@ static const int PICTURE_FORMAT_JPEG = 1;
 static const int PICTURE_FORMAT_RAW = 2;
 
 /* Default preview width in pixels */
-#define DEFAULT_USBCAM_PRVW_WD  1280//640
+#define DEFAULT_USBCAM_PRVW_WD  640
 
 /* Default preview height in pixels */
-#define DEFAULT_USBCAM_PRVW_HT  720//480
+#define DEFAULT_USBCAM_PRVW_HT  480
 
 /* Default picture format */
-#define DEFAULT_USBCAM_PICT_FMT     PICTURE_FORMAT_JPEG
+#define DEFAULT_USBCAM_PICT_FMT     PICTURE_FORMAT_RAW
 
 /* Default picture width in pixels */
 #define DEFAULT_USBCAM_PICT_WD  640
@@ -80,13 +80,13 @@ static const int PICTURE_FORMAT_RAW = 2;
 #define DEFAULT_USBCAM_PICT_QLTY  85
 
 /* Default thumbnail width in pixels */
-#define DEFAULT_USBCAM_THUMBNAIL_WD    432
+#define DEFAULT_USBCAM_THUMBNAIL_WD    352
 
 /* Default thumbnail height in pixels */
 #define DEFAULT_USBCAM_THUMBNAIL_HT    288
 
 /* Default thumbnail JPEG quality 0-100 */
-#define DEFAULT_USBCAM_THUMBNAIL_QLTY  85
+#define DEFAULT_USBCAM_THUMBNAIL_QLTY  90
 
 /* Default preview format */
 #define DEFAULT_USBCAM_PRVW_FMT HAL_PIXEL_FORMAT_YCrCb_420_SP
diff --git a/usbcamcore/src/QCameraUsbParm.cpp b/usbcamcore/src/QCameraUsbParm.cpp
index fda6e9d..4bfac42 100755
--- a/usbcamcore/src/QCameraUsbParm.cpp
+++ b/usbcamcore/src/QCameraUsbParm.cpp
@@ -94,12 +94,18 @@ static const preview_format_info_t preview_format_info_list[] = {
 };
 
 static struct camera_size_type previewSizes[] = {
-    { 1920, 1088}, //1080p
-    { 1280, 720}, // 720P,
-    { 640, 480}, // VGA
-    { 512, 384},
-    { 480, 320},
-    { 320, 240}, // QVGA
+    {1920, 1088},
+    {1280, 800},
+    {1280, 720},
+    {1024, 768},
+    {848, 480},
+    {800, 600},
+    {640, 480},
+    {640, 360},
+    {352, 288},
+    {320, 240},
+    {176, 144},
+    {160, 120}
 };
 
 // All fps ranges which can be supported. This list will be filtered according
@@ -118,14 +124,22 @@ static const str_map frame_rate_modes[] = {
 
 static const str_map picture_formats[] = {
     {QCameraParameters::PIXEL_FORMAT_JPEG, PICTURE_FORMAT_JPEG},
-    //{QCameraParameters::PIXEL_FORMAT_RAW, PICTURE_FORMAT_RAW}
+    {QCameraParameters::PIXEL_FORMAT_RAW, PICTURE_FORMAT_RAW}
 };
 
 static camera_size_type picture_sizes[] = {
-    { 1920, 1088}, //HD1080
-    { 1280, 720}, //HD720
-    { 640, 480}, // VGA
-    { 320, 240}, // QVGA
+    {1920, 1088},
+    {1280, 800},
+    {1280, 720},
+    {1024, 768},
+    {848, 480},
+    {800, 600},
+    {640, 480},
+    {640, 360},
+    {352, 288},
+    {320, 240},
+    {176, 144},
+    {160, 120}
 };
 
 /* aspect ratio removed */
diff --git a/usbcamcore/src/QualcommUsbCamera.cpp b/usbcamcore/src/QualcommUsbCamera.cpp
index b274626..2351d8b 100755
--- a/usbcamcore/src/QualcommUsbCamera.cpp
+++ b/usbcamcore/src/QualcommUsbCamera.cpp
@@ -90,7 +90,7 @@ camera_device_ops_t usbcam_camera_ops = {
 #define CALL_BACK               1
 #define MEMSET                  0
 #define FREAD_JPEG_PICTURE      0
-#define JPEG_ON_USB_CAMERA      1
+#define JPEG_ON_USB_CAMERA      0
 #define FILE_DUMP_CAMERA        0
 #define FILE_DUMP_B4_DISP       0
 
@@ -162,7 +162,7 @@ extern "C" int usbcam_get_camera_info(int camera_id, struct camera_info *info)
         struct CameraInfo camInfo;
         memset(&camInfo, -1, sizeof (struct CameraInfo));
 
-        info->facing = CAMERA_FACING_FRONT;//CAMERA_FACING_BACK;
+        info->facing = CAMERA_FACING_BACK;//CAMERA_FACING_FRONT
         info->orientation = 0;
         rc = 0;
     }


另一个差异/hardware/qcom/camera/usbcamcore

diff --git a/usbcamcore/inc/QCameraUsbParm.h b/usbcamcore/inc/QCameraUsbParm.h
index c47ef1f..2a1a92a 100755
--- a/usbcamcore/inc/QCameraUsbParm.h
+++ b/usbcamcore/inc/QCameraUsbParm.h
@@ -60,6 +60,7 @@ extern "C" {
 /* enum definitions for picture formats */
 static const int PICTURE_FORMAT_JPEG = 1;
 static const int PICTURE_FORMAT_RAW = 2;
+static const int PICTURE_FORMAT_YUV = 3;
 
 /* Default preview width in pixels */
 #define DEFAULT_USBCAM_PRVW_WD  1280//640
@@ -68,7 +69,7 @@ static const int PICTURE_FORMAT_RAW = 2;
 #define DEFAULT_USBCAM_PRVW_HT  720//480
 
 /* Default picture format */
-#define DEFAULT_USBCAM_PICT_FMT     PICTURE_FORMAT_RAW
+#define DEFAULT_USBCAM_PICT_FMT     PICTURE_FORMAT_YUV
 
 /* Default picture width in pixels */
 #define DEFAULT_USBCAM_PICT_WD  640
@@ -89,7 +90,7 @@ static const int PICTURE_FORMAT_RAW = 2;
 #define DEFAULT_USBCAM_THUMBNAIL_QLTY  85
 
 /* Default preview format */
-#define DEFAULT_USBCAM_PRVW_FMT HAL_PIXEL_FORMAT_YCrCb_420_SP
+#define DEFAULT_USBCAM_PRVW_FMT HAL_PIXEL_FORMAT_YV12
 
 /* minimum of the default preview fps range in milli-Hz */
 #define MIN_PREV_FPS            5000
diff --git a/usbcamcore/src/QCameraUsbParm.cpp b/usbcamcore/src/QCameraUsbParm.cpp
index 4bfac42..4393a35 100755
--- a/usbcamcore/src/QCameraUsbParm.cpp
+++ b/usbcamcore/src/QCameraUsbParm.cpp
@@ -26,7 +26,7 @@
  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-//#define ALOG_NDEBUG 0
+#define ALOG_NDEBUG 0
 #define ALOG_NIDEBUG 0
 #define LOG_TAG "QCameraUsbParm"
 #include <utils/Log.h>
@@ -86,7 +86,8 @@ namespace android {
 
 /********************************************************************/
 static const str_map preview_formats[] = {
-    {QCameraParameters::PIXEL_FORMAT_YUV420SP, HAL_PIXEL_FORMAT_YCrCb_420_SP},
+    {QCameraParameters::PIXEL_FORMAT_YUV420P, HAL_PIXEL_FORMAT_YV12},
+    {QCameraParameters::PIXEL_FORMAT_YUV420SP, HAL_PIXEL_FORMAT_YCrCb_420_SP}
 };
 
 static const preview_format_info_t preview_format_info_list[] = {
@@ -124,7 +125,8 @@ static const str_map frame_rate_modes[] = {
 
 static const str_map picture_formats[] = {
     {QCameraParameters::PIXEL_FORMAT_JPEG, PICTURE_FORMAT_JPEG},
-    {QCameraParameters::PIXEL_FORMAT_RAW, PICTURE_FORMAT_RAW}
+    {QCameraParameters::PIXEL_FORMAT_RAW, PICTURE_FORMAT_RAW},
+    {QCameraParameters::PIXEL_FORMAT_YUV420P, PICTURE_FORMAT_YUV}
 };
 
 static camera_size_type picture_sizes[] = {

该项目耗时近4个月,希望您对此表示感谢。我也希望它能在经过适当审查后的某天成为Google源代码的一部分。