【问题标题】:Android Open external UVC camera instead hardware cameraAndroid 打开外部 UVC 摄像头而不是硬件摄像头
【发布时间】:2016-06-15 07:09:08
【问题描述】:

我需要打开外部 UVC 摄像头

Camera.open(CameraId);

但不工作

请帮忙?

【问题讨论】:

    标签: android android-camera


    【解决方案1】:

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

    1. 有一个本机库可用于访问外部 UVC 摄像头https://github.com/ktossell/libuvc。我发现这个项目使用了它,当我编译和测试它时,我发现样本只是部分稳定,而且它承载的源代码不堪重负。
    2. 已有 2 年历史的 Camera2 API 似乎包含外部摄像头支持。我在Android project documentation - Camera device 中发现了以下语句:

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

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

    最后,我什至在Android source code 中发现了以下代码

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

    而 CAMERA_FACING_EXTERNAL 是 CameraInfo class 的新值,用于显然不是正面和背面的外部摄像头。

    我希望这将帮助您获得完整的答案。

    【讨论】:

    • 嗨。你有什么关于 Camera2 AI 和网络摄像头的消息吗?
    • 嘿,4年后有什么进展吗?我正在做一个类似的项目,外部 USB 摄像头访问仍然几乎不存在。
    • 永远不会成功,项目也永远不会完成......
    【解决方案2】:

    不幸的是,虽然 camera2 API 确实具有支持外部摄像头(如 USB 网络摄像头)所需的 API 接口,但目前还没有对外部摄像头的标准低级支持。

    一些个别设备制造商确实有这样的支持,但目前这是极少数的设备。

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

    【讨论】:

      【解决方案3】:

      久经考验:https://github.com/saki4510t/UVCCamera

      上面的链接在一个主应用程序中包含 8 个不同的应用程序,每个应用程序实现不同的功能。浏览应用程序。

      使用 libuvc 库访问外部摄像头。

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          【解决方案5】:

          此功能已在某些平台上实现,方法是将硬件上的 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,
          };
          

          【讨论】:

            【解决方案6】:

            USB 摄像头不适用于较新的 camera2 api

            更新:它们与 Camera2 API 一起工作正常,但间歇性地使用 NumberFormatException 作为 cameraID [USB 相机的 ID 类似于 /dev/video1]。因此我不能告诉我该怎么做。

            旧的 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 个月的时间,希望大家多多支持。另外我希望它可以在经过适当审查后成为谷歌源代码的一部分。

            【讨论】:

              猜你喜欢
              • 2021-01-23
              • 1970-01-01
              • 2014-09-28
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多