Loading camera/device/3.4/default/ExternalCameraDevice.cpp +19 −5 Original line number Original line Diff line number Diff line Loading @@ -42,6 +42,9 @@ const std::array<uint32_t, /*size*/1> kSupportedFourCCs {{ V4L2_PIX_FMT_MJPEG V4L2_PIX_FMT_MJPEG }}; // double braces required in C++11 }}; // double braces required in C++11 constexpr int MAX_RETRY = 5; // Allow retry v4l2 open failures a few times. constexpr int OPEN_RETRY_SLEEP_US = 100000; // 100ms * MAX_RETRY = 0.5 seconds } // anonymous namespace } // anonymous namespace ExternalCameraDevice::ExternalCameraDevice( ExternalCameraDevice::ExternalCameraDevice( Loading Loading @@ -121,6 +124,16 @@ Return<void> ExternalCameraDevice::open( } } unique_fd fd(::open(mCameraId.c_str(), O_RDWR)); unique_fd fd(::open(mCameraId.c_str(), O_RDWR)); if (fd.get() < 0) { int numAttempt = 0; do { ALOGW("%s: v4l2 device %s open failed, wait 33ms and try again", __FUNCTION__, mCameraId.c_str()); usleep(OPEN_RETRY_SLEEP_US); // sleep and try again fd.reset(::open(mCameraId.c_str(), O_RDWR)); numAttempt++; } while (fd.get() < 0 && numAttempt <= MAX_RETRY); if (fd.get() < 0) { if (fd.get() < 0) { ALOGE("%s: v4l2 device open %s failed: %s", ALOGE("%s: v4l2 device open %s failed: %s", __FUNCTION__, mCameraId.c_str(), strerror(errno)); __FUNCTION__, mCameraId.c_str(), strerror(errno)); Loading @@ -128,6 +141,7 @@ Return<void> ExternalCameraDevice::open( _hidl_cb(Status::INTERNAL_ERROR, nullptr); _hidl_cb(Status::INTERNAL_ERROR, nullptr); return Void(); return Void(); } } } session = new ExternalCameraDeviceSession( session = new ExternalCameraDeviceSession( callback, mCfg, mSupportedFormats, mCroppingType, callback, mCfg, mSupportedFormats, mCroppingType, Loading camera/device/3.4/default/ExternalCameraDeviceSession.cpp +39 −2 Original line number Original line Diff line number Diff line Loading @@ -49,7 +49,7 @@ const int kBadFramesAfterStreamOn = 1; // drop x frames after streamOn to get ri // method // method constexpr int MAX_RETRY = 15; // Allow retry some ioctl failures a few times to account for some constexpr int MAX_RETRY = 15; // Allow retry some ioctl failures a few times to account for some // webcam showing temporarily ioctl failures. // webcam showing temporarily ioctl failures. constexpr int IOCTL_RETRY_SLEEP_US = 33000; // 33ms * MAX_RETRY = 5 seconds constexpr int IOCTL_RETRY_SLEEP_US = 33000; // 33ms * MAX_RETRY = 0.5 seconds // Constants for tryLock during dumpstate // Constants for tryLock during dumpstate static constexpr int kDumpLockRetries = 50; static constexpr int kDumpLockRetries = 50; Loading Loading @@ -115,6 +115,35 @@ bool ExternalCameraDeviceSession::initialize() { return true; return true; } } struct v4l2_capability capability; int ret = ioctl(mV4l2Fd.get(), VIDIOC_QUERYCAP, &capability); std::string make, model; if (ret < 0) { ALOGW("%s v4l2 QUERYCAP failed", __FUNCTION__); make = "Generic UVC webcam"; model = "Generic UVC webcam"; } else { // capability.card is UTF-8 encoded char card[32]; int j = 0; for (int i = 0; i < 32; i++) { if (capability.card[i] < 128) { card[j++] = capability.card[i]; } if (capability.card[i] == '\0') { break; } } if (j == 0 || card[j - 1] != '\0') { make = "Generic UVC webcam"; model = "Generic UVC webcam"; } else { make = card; model = card; } } mOutputThread->setExifMakeModel(make, model); status_t status = initDefaultRequests(); status_t status = initDefaultRequests(); if (status != OK) { if (status != OK) { ALOGE("%s: init default requests failed!", __FUNCTION__); ALOGE("%s: init default requests failed!", __FUNCTION__); Loading Loading @@ -826,6 +855,12 @@ ExternalCameraDeviceSession::OutputThread::OutputThread( ExternalCameraDeviceSession::OutputThread::~OutputThread() {} ExternalCameraDeviceSession::OutputThread::~OutputThread() {} void ExternalCameraDeviceSession::OutputThread::setExifMakeModel( const std::string& make, const std::string& model) { mExifMake = make; mExifModel = model; } uint32_t ExternalCameraDeviceSession::OutputThread::getFourCcFromLayout( uint32_t ExternalCameraDeviceSession::OutputThread::getFourCcFromLayout( const YCbCrLayout& layout) { const YCbCrLayout& layout) { intptr_t cb = reinterpret_cast<intptr_t>(layout.cb); intptr_t cb = reinterpret_cast<intptr_t>(layout.cb); Loading Loading @@ -1611,6 +1646,8 @@ int ExternalCameraDeviceSession::OutputThread::createJpegLocked( utils->initialize(); utils->initialize(); utils->setFromMetadata(meta, jpegSize.width, jpegSize.height); utils->setFromMetadata(meta, jpegSize.width, jpegSize.height); utils->setMake(mExifMake); utils->setModel(mExifModel); ret = utils->generateApp1(outputThumbnail ? &thumbCode[0] : 0, thumbCodeSize); ret = utils->generateApp1(outputThumbnail ? &thumbCode[0] : 0, thumbCodeSize); Loading Loading @@ -2150,7 +2187,7 @@ int ExternalCameraDeviceSession::configureV4l2StreamLocked( int numAttempt = 0; int numAttempt = 0; while (ret < 0) { while (ret < 0) { ALOGW("%s: VIDIOC_S_FMT failed, wait 33ms and try again", __FUNCTION__); ALOGW("%s: VIDIOC_S_FMT failed, wait 33ms and try again", __FUNCTION__); usleep(IOCTL_RETRY_SLEEP_US); // sleep 100 ms and try again usleep(IOCTL_RETRY_SLEEP_US); // sleep and try again ret = TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_S_FMT, &fmt)); ret = TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_S_FMT, &fmt)); if (numAttempt == MAX_RETRY) { if (numAttempt == MAX_RETRY) { break; break; Loading camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h +4 −0 Original line number Original line Diff line number Diff line Loading @@ -231,6 +231,7 @@ protected: void dump(int fd); void dump(int fd); virtual bool threadLoop() override; virtual bool threadLoop() override; void setExifMakeModel(const std::string& make, const std::string& model); private: private: static const uint32_t FLEX_YUV_GENERIC = static_cast<uint32_t>('F') | static const uint32_t FLEX_YUV_GENERIC = static_cast<uint32_t>('F') | static_cast<uint32_t>('L') << 8 | static_cast<uint32_t>('E') << 16 | static_cast<uint32_t>('L') << 8 | static_cast<uint32_t>('E') << 16 | Loading Loading @@ -288,6 +289,9 @@ protected: std::unordered_map<Size, sp<AllocatedFrame>, SizeHasher> mScaledYu12Frames; std::unordered_map<Size, sp<AllocatedFrame>, SizeHasher> mScaledYu12Frames; YCbCrLayout mYu12FrameLayout; YCbCrLayout mYu12FrameLayout; YCbCrLayout mYu12ThumbFrameLayout; YCbCrLayout mYu12ThumbFrameLayout; std::string mExifMake; std::string mExifModel; }; }; // Protect (most of) HIDL interface methods from synchronized-entering // Protect (most of) HIDL interface methods from synchronized-entering Loading camera/provider/2.4/default/ExternalCameraProvider.cpp +19 −13 Original line number Original line Diff line number Diff line Loading @@ -164,29 +164,35 @@ void ExternalCameraProvider::addExternalCamera(const char* devName) { } } void ExternalCameraProvider::deviceAdded(const char* devName) { void ExternalCameraProvider::deviceAdded(const char* devName) { int fd = -1; { if ((fd = ::open(devName, O_RDWR)) < 0) { base::unique_fd fd(::open(devName, O_RDWR)); if (fd.get() < 0) { ALOGE("%s open v4l2 device %s failed:%s", __FUNCTION__, devName, strerror(errno)); ALOGE("%s open v4l2 device %s failed:%s", __FUNCTION__, devName, strerror(errno)); return; return; } } do { struct v4l2_capability capability; struct v4l2_capability capability; int ret = ioctl(fd, VIDIOC_QUERYCAP, &capability); int ret = ioctl(fd.get(), VIDIOC_QUERYCAP, &capability); if (ret < 0) { if (ret < 0) { ALOGE("%s v4l2 QUERYCAP %s failed", __FUNCTION__, devName); ALOGE("%s v4l2 QUERYCAP %s failed", __FUNCTION__, devName); break; return; } } if (!(capability.device_caps & V4L2_CAP_VIDEO_CAPTURE)) { if (!(capability.device_caps & V4L2_CAP_VIDEO_CAPTURE)) { ALOGW("%s device %s does not support VIDEO_CAPTURE", __FUNCTION__, devName); ALOGW("%s device %s does not support VIDEO_CAPTURE", __FUNCTION__, devName); break; return; } } } // See if we can initialize ExternalCameraDevice correctly sp<device::V3_4::implementation::ExternalCameraDevice> deviceImpl = new device::V3_4::implementation::ExternalCameraDevice(devName, mCfg); if (deviceImpl == nullptr || deviceImpl->isInitFailed()) { ALOGW("%s: Attempt to init camera device %s failed!", __FUNCTION__, devName); return; } deviceImpl.clear(); addExternalCamera(devName); addExternalCamera(devName); } while (0); close(fd); return; return; } } Loading Loading
camera/device/3.4/default/ExternalCameraDevice.cpp +19 −5 Original line number Original line Diff line number Diff line Loading @@ -42,6 +42,9 @@ const std::array<uint32_t, /*size*/1> kSupportedFourCCs {{ V4L2_PIX_FMT_MJPEG V4L2_PIX_FMT_MJPEG }}; // double braces required in C++11 }}; // double braces required in C++11 constexpr int MAX_RETRY = 5; // Allow retry v4l2 open failures a few times. constexpr int OPEN_RETRY_SLEEP_US = 100000; // 100ms * MAX_RETRY = 0.5 seconds } // anonymous namespace } // anonymous namespace ExternalCameraDevice::ExternalCameraDevice( ExternalCameraDevice::ExternalCameraDevice( Loading Loading @@ -121,6 +124,16 @@ Return<void> ExternalCameraDevice::open( } } unique_fd fd(::open(mCameraId.c_str(), O_RDWR)); unique_fd fd(::open(mCameraId.c_str(), O_RDWR)); if (fd.get() < 0) { int numAttempt = 0; do { ALOGW("%s: v4l2 device %s open failed, wait 33ms and try again", __FUNCTION__, mCameraId.c_str()); usleep(OPEN_RETRY_SLEEP_US); // sleep and try again fd.reset(::open(mCameraId.c_str(), O_RDWR)); numAttempt++; } while (fd.get() < 0 && numAttempt <= MAX_RETRY); if (fd.get() < 0) { if (fd.get() < 0) { ALOGE("%s: v4l2 device open %s failed: %s", ALOGE("%s: v4l2 device open %s failed: %s", __FUNCTION__, mCameraId.c_str(), strerror(errno)); __FUNCTION__, mCameraId.c_str(), strerror(errno)); Loading @@ -128,6 +141,7 @@ Return<void> ExternalCameraDevice::open( _hidl_cb(Status::INTERNAL_ERROR, nullptr); _hidl_cb(Status::INTERNAL_ERROR, nullptr); return Void(); return Void(); } } } session = new ExternalCameraDeviceSession( session = new ExternalCameraDeviceSession( callback, mCfg, mSupportedFormats, mCroppingType, callback, mCfg, mSupportedFormats, mCroppingType, Loading
camera/device/3.4/default/ExternalCameraDeviceSession.cpp +39 −2 Original line number Original line Diff line number Diff line Loading @@ -49,7 +49,7 @@ const int kBadFramesAfterStreamOn = 1; // drop x frames after streamOn to get ri // method // method constexpr int MAX_RETRY = 15; // Allow retry some ioctl failures a few times to account for some constexpr int MAX_RETRY = 15; // Allow retry some ioctl failures a few times to account for some // webcam showing temporarily ioctl failures. // webcam showing temporarily ioctl failures. constexpr int IOCTL_RETRY_SLEEP_US = 33000; // 33ms * MAX_RETRY = 5 seconds constexpr int IOCTL_RETRY_SLEEP_US = 33000; // 33ms * MAX_RETRY = 0.5 seconds // Constants for tryLock during dumpstate // Constants for tryLock during dumpstate static constexpr int kDumpLockRetries = 50; static constexpr int kDumpLockRetries = 50; Loading Loading @@ -115,6 +115,35 @@ bool ExternalCameraDeviceSession::initialize() { return true; return true; } } struct v4l2_capability capability; int ret = ioctl(mV4l2Fd.get(), VIDIOC_QUERYCAP, &capability); std::string make, model; if (ret < 0) { ALOGW("%s v4l2 QUERYCAP failed", __FUNCTION__); make = "Generic UVC webcam"; model = "Generic UVC webcam"; } else { // capability.card is UTF-8 encoded char card[32]; int j = 0; for (int i = 0; i < 32; i++) { if (capability.card[i] < 128) { card[j++] = capability.card[i]; } if (capability.card[i] == '\0') { break; } } if (j == 0 || card[j - 1] != '\0') { make = "Generic UVC webcam"; model = "Generic UVC webcam"; } else { make = card; model = card; } } mOutputThread->setExifMakeModel(make, model); status_t status = initDefaultRequests(); status_t status = initDefaultRequests(); if (status != OK) { if (status != OK) { ALOGE("%s: init default requests failed!", __FUNCTION__); ALOGE("%s: init default requests failed!", __FUNCTION__); Loading Loading @@ -826,6 +855,12 @@ ExternalCameraDeviceSession::OutputThread::OutputThread( ExternalCameraDeviceSession::OutputThread::~OutputThread() {} ExternalCameraDeviceSession::OutputThread::~OutputThread() {} void ExternalCameraDeviceSession::OutputThread::setExifMakeModel( const std::string& make, const std::string& model) { mExifMake = make; mExifModel = model; } uint32_t ExternalCameraDeviceSession::OutputThread::getFourCcFromLayout( uint32_t ExternalCameraDeviceSession::OutputThread::getFourCcFromLayout( const YCbCrLayout& layout) { const YCbCrLayout& layout) { intptr_t cb = reinterpret_cast<intptr_t>(layout.cb); intptr_t cb = reinterpret_cast<intptr_t>(layout.cb); Loading Loading @@ -1611,6 +1646,8 @@ int ExternalCameraDeviceSession::OutputThread::createJpegLocked( utils->initialize(); utils->initialize(); utils->setFromMetadata(meta, jpegSize.width, jpegSize.height); utils->setFromMetadata(meta, jpegSize.width, jpegSize.height); utils->setMake(mExifMake); utils->setModel(mExifModel); ret = utils->generateApp1(outputThumbnail ? &thumbCode[0] : 0, thumbCodeSize); ret = utils->generateApp1(outputThumbnail ? &thumbCode[0] : 0, thumbCodeSize); Loading Loading @@ -2150,7 +2187,7 @@ int ExternalCameraDeviceSession::configureV4l2StreamLocked( int numAttempt = 0; int numAttempt = 0; while (ret < 0) { while (ret < 0) { ALOGW("%s: VIDIOC_S_FMT failed, wait 33ms and try again", __FUNCTION__); ALOGW("%s: VIDIOC_S_FMT failed, wait 33ms and try again", __FUNCTION__); usleep(IOCTL_RETRY_SLEEP_US); // sleep 100 ms and try again usleep(IOCTL_RETRY_SLEEP_US); // sleep and try again ret = TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_S_FMT, &fmt)); ret = TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_S_FMT, &fmt)); if (numAttempt == MAX_RETRY) { if (numAttempt == MAX_RETRY) { break; break; Loading
camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h +4 −0 Original line number Original line Diff line number Diff line Loading @@ -231,6 +231,7 @@ protected: void dump(int fd); void dump(int fd); virtual bool threadLoop() override; virtual bool threadLoop() override; void setExifMakeModel(const std::string& make, const std::string& model); private: private: static const uint32_t FLEX_YUV_GENERIC = static_cast<uint32_t>('F') | static const uint32_t FLEX_YUV_GENERIC = static_cast<uint32_t>('F') | static_cast<uint32_t>('L') << 8 | static_cast<uint32_t>('E') << 16 | static_cast<uint32_t>('L') << 8 | static_cast<uint32_t>('E') << 16 | Loading Loading @@ -288,6 +289,9 @@ protected: std::unordered_map<Size, sp<AllocatedFrame>, SizeHasher> mScaledYu12Frames; std::unordered_map<Size, sp<AllocatedFrame>, SizeHasher> mScaledYu12Frames; YCbCrLayout mYu12FrameLayout; YCbCrLayout mYu12FrameLayout; YCbCrLayout mYu12ThumbFrameLayout; YCbCrLayout mYu12ThumbFrameLayout; std::string mExifMake; std::string mExifModel; }; }; // Protect (most of) HIDL interface methods from synchronized-entering // Protect (most of) HIDL interface methods from synchronized-entering Loading
camera/provider/2.4/default/ExternalCameraProvider.cpp +19 −13 Original line number Original line Diff line number Diff line Loading @@ -164,29 +164,35 @@ void ExternalCameraProvider::addExternalCamera(const char* devName) { } } void ExternalCameraProvider::deviceAdded(const char* devName) { void ExternalCameraProvider::deviceAdded(const char* devName) { int fd = -1; { if ((fd = ::open(devName, O_RDWR)) < 0) { base::unique_fd fd(::open(devName, O_RDWR)); if (fd.get() < 0) { ALOGE("%s open v4l2 device %s failed:%s", __FUNCTION__, devName, strerror(errno)); ALOGE("%s open v4l2 device %s failed:%s", __FUNCTION__, devName, strerror(errno)); return; return; } } do { struct v4l2_capability capability; struct v4l2_capability capability; int ret = ioctl(fd, VIDIOC_QUERYCAP, &capability); int ret = ioctl(fd.get(), VIDIOC_QUERYCAP, &capability); if (ret < 0) { if (ret < 0) { ALOGE("%s v4l2 QUERYCAP %s failed", __FUNCTION__, devName); ALOGE("%s v4l2 QUERYCAP %s failed", __FUNCTION__, devName); break; return; } } if (!(capability.device_caps & V4L2_CAP_VIDEO_CAPTURE)) { if (!(capability.device_caps & V4L2_CAP_VIDEO_CAPTURE)) { ALOGW("%s device %s does not support VIDEO_CAPTURE", __FUNCTION__, devName); ALOGW("%s device %s does not support VIDEO_CAPTURE", __FUNCTION__, devName); break; return; } } } // See if we can initialize ExternalCameraDevice correctly sp<device::V3_4::implementation::ExternalCameraDevice> deviceImpl = new device::V3_4::implementation::ExternalCameraDevice(devName, mCfg); if (deviceImpl == nullptr || deviceImpl->isInitFailed()) { ALOGW("%s: Attempt to init camera device %s failed!", __FUNCTION__, devName); return; } deviceImpl.clear(); addExternalCamera(devName); addExternalCamera(devName); } while (0); close(fd); return; return; } } Loading