Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5d901420 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Camera: various external camera fixes" into pi-dev

parents 6acac5a3 2d61bfd2
Loading
Loading
Loading
Loading
+19 −5
Original line number Diff line number Diff line
@@ -42,6 +42,9 @@ const std::array<uint32_t, /*size*/1> kSupportedFourCCs {{
    V4L2_PIX_FMT_MJPEG
}}; // 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

ExternalCameraDevice::ExternalCameraDevice(
@@ -121,6 +124,16 @@ Return<void> ExternalCameraDevice::open(
    }

    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) {
            ALOGE("%s: v4l2 device open %s failed: %s",
                    __FUNCTION__, mCameraId.c_str(), strerror(errno));
@@ -128,6 +141,7 @@ Return<void> ExternalCameraDevice::open(
            _hidl_cb(Status::INTERNAL_ERROR, nullptr);
            return Void();
        }
    }

    session = new ExternalCameraDeviceSession(
            callback, mCfg, mSupportedFormats, mCroppingType,
+39 −2
Original line number Diff line number Diff line
@@ -49,7 +49,7 @@ const int kBadFramesAfterStreamOn = 1; // drop x frames after streamOn to get ri
                                       // method
constexpr int MAX_RETRY = 15; // Allow retry some ioctl failures a few times to account for some
                             // 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
static constexpr int kDumpLockRetries = 50;
@@ -115,6 +115,35 @@ bool ExternalCameraDeviceSession::initialize() {
        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();
    if (status != OK) {
        ALOGE("%s: init default requests failed!", __FUNCTION__);
@@ -826,6 +855,12 @@ 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(
        const YCbCrLayout& layout) {
    intptr_t cb = reinterpret_cast<intptr_t>(layout.cb);
@@ -1611,6 +1646,8 @@ int ExternalCameraDeviceSession::OutputThread::createJpegLocked(
    utils->initialize();

    utils->setFromMetadata(meta, jpegSize.width, jpegSize.height);
    utils->setMake(mExifMake);
    utils->setModel(mExifModel);

    ret = utils->generateApp1(outputThumbnail ? &thumbCode[0] : 0, thumbCodeSize);

@@ -2150,7 +2187,7 @@ int ExternalCameraDeviceSession::configureV4l2StreamLocked(
        int numAttempt = 0;
        while (ret < 0) {
            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));
            if (numAttempt == MAX_RETRY) {
                break;
+4 −0
Original line number Diff line number Diff line
@@ -231,6 +231,7 @@ protected:
        void dump(int fd);
        virtual bool threadLoop() override;

        void setExifMakeModel(const std::string& make, const std::string& model);
    private:
        static const uint32_t FLEX_YUV_GENERIC = static_cast<uint32_t>('F') |
                static_cast<uint32_t>('L') << 8 | static_cast<uint32_t>('E') << 16 |
@@ -288,6 +289,9 @@ protected:
        std::unordered_map<Size, sp<AllocatedFrame>, SizeHasher> mScaledYu12Frames;
        YCbCrLayout mYu12FrameLayout;
        YCbCrLayout mYu12ThumbFrameLayout;

        std::string mExifMake;
        std::string mExifModel;
    };

    // Protect (most of) HIDL interface methods from synchronized-entering
+19 −13
Original line number Diff line number Diff line
@@ -164,29 +164,35 @@ void ExternalCameraProvider::addExternalCamera(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));
            return;
        }

    do {
        struct v4l2_capability capability;
        int ret = ioctl(fd, VIDIOC_QUERYCAP, &capability);
        int ret = ioctl(fd.get(), VIDIOC_QUERYCAP, &capability);
        if (ret < 0) {
            ALOGE("%s v4l2 QUERYCAP %s failed", __FUNCTION__, devName);
            break;
            return;
        }

        if (!(capability.device_caps & V4L2_CAP_VIDEO_CAPTURE)) {
            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);
    } while (0);

    close(fd);
    return;
}