1. 程式人生 > >Android之Camera預覽過程中插拔攝像頭節點後移

Android之Camera預覽過程中插拔攝像頭節點後移

現象:

在使用Camera Preview時;熱插拔攝像頭會導致裝置節點由/dev/video0變為/dev/video1,或者插入多個video裝置時,會變為/dev/video1、/dev/video2......。

一、首先看裝置節點的建立

drivers/media/video/uvc/uvc_driver.c

static int uvc_probe(struct usb_interface *intf,
              const struct usb_device_id *id){
  if (v4l2_device_register(&intf->dev, &dev->vdev) < 0)
    goto error;
}

drivers/media/video/v4l2-devices.c

int v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev)
{
  err = __video_register_device(vdev, VFL_TYPE_SUBDEV, -1, 1,  sd->owner);
}

drivers/media/video/v4l2-dev.c

int __video_register_device(struct video_device *vdev, int type, int nr,
         int warn_if_nr_in_use, struct module *owner){
  int nr = -1; int minor_cnt = 64;
  nr = devnode_find(vdev, nr == -1 ? 0 : nr, minor_cnt); //裝置節點名,即“/dev/video*”
  vdev->num = nr;
  devnode_set(vdev); //該vdev->numd對應的符號被置為1
  /*
  devnode_set(vdev); //該vdev->numd對應的符號被置為1
  devnode_clear(vdev); //該vdev->numd對應的符號被置為0
  */
  name_base = "video";
  dev_set_name(&vdev->dev, "%s%d", name_base, vdev->num);
  ret = device_register(&vdev->dev);
  vdev->dev.release = v4l2_device_release; //該介面會呼叫devnode_clear(vdev)
}

二、問題解決

最終修改,問題解決:

drivers/media/video/uvc/uvc_driver.c

static void uvc_disconnect(struct usb_interface *intf){
  uvc_unregister_video(dev);
}
static void uvc_unregister_video(struct uvc_device *dev){
  video_unregister_device(stream->vdev); //修改該介面函式
  if (atomic_dec_and_test(&dev->nstreams)){  //這裡也有些問題,但不是根本原因
    uvc_delete(dev);
  }
}

我的修改:

drivers/media/video/v4l2-dev.c

void video_unregister_device(struct video_device *vdev){
  devnode_clear(vdev);//add by tankai
  device_unregister(&vdev->dev); //該介面本身會呼叫v4l2_device_release,但卻沒有
}
三、其他解決辦法

1.這是一個網友在HAL層的解決辦法

2.我們在HAL的解決辦法

hardware/amlogic/camera/AppCallbackNotifier.cpp

//All sub-components of Camera HAL call this whenever any error happens
void AppCallbackNotifier::errorNotify(int error)
{
    LOG_FUNCTION_NAME;


    CAMHAL_LOGEB("AppCallbackNotifier received error %d", error);


    // If it is a fatal error abort here!
    if((error == CAMERA_ERROR_FATAL) || (error == CAMERA_ERROR_HARD)) {
        //We kill media server if we encounter these errors as there is
        //no point continuing and apps also don't handle errors other
        //than media server death always.
        abort();
        return;
    }


    if (  ( NULL != mCameraHal ) &&
          ( NULL != mNotifyCb ) &&
          ( mCameraHal->msgTypeEnabled(CAMERA_MSG_ERROR) ) )
      {
        CAMHAL_LOGEB("AppCallbackNotifier mNotifyCb %d", error);
        mNotifyCb(CAMERA_MSG_ERROR, CAMERA_ERROR_UNKNOWN, 0, mCallbackCookie);
        mCameraHal->release(); //add by tankai
      }


    LOG_FUNCTION_NAME_EXIT;
}