| /* |
| * Copyright (C) 2015-2020 Intel Corporation. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| #define LOG_TAG "SofSource" |
| |
| #include <poll.h> |
| |
| #include "iutils/CameraLog.h" |
| #include "iutils/Utils.h" |
| #include "V4l2DeviceFactory.h" |
| #include "PlatformData.h" |
| |
| #include "SofSource.h" |
| |
| namespace icamera { |
| |
| SofSource::SofSource(int cameraId) : |
| mPollThread(nullptr), |
| mCameraId(cameraId), |
| mIsysReceiverSubDev(nullptr), |
| mExitPending(false) |
| { |
| LOG1("%s: SofSource is constructed", __func__); |
| |
| mSofDisabled = !PlatformData::isEnableAIQ(mCameraId); |
| |
| mSofDisabled = mSofDisabled || !PlatformData::isIsysEnabled(cameraId); |
| } |
| |
| SofSource::~SofSource() |
| { |
| LOG1("%s: SofSource is distructed.", __func__); |
| } |
| |
| int SofSource::init() |
| { |
| if (mSofDisabled) { |
| return OK; |
| } |
| |
| mPollThread = new PollThread(this); |
| |
| return OK; |
| } |
| |
| int SofSource::deinit() |
| { |
| if (mSofDisabled) { |
| return OK; |
| } |
| |
| int status = deinitDev(); |
| mPollThread->join(); |
| delete mPollThread; |
| return status; |
| } |
| |
| int SofSource::initDev() |
| { |
| //Create and open receiver subdevice. |
| std::string subDeviceNodeName; |
| |
| if (PlatformData::getDevNameByType(mCameraId, VIDEO_ISYS_RECEIVER, subDeviceNodeName) == OK) { |
| LOG1("%s: found ISYS receiver subdevice %s", __func__, subDeviceNodeName.c_str()); |
| } |
| |
| deinitDev(); |
| |
| mIsysReceiverSubDev = V4l2DeviceFactory::getSubDev(mCameraId, subDeviceNodeName); |
| |
| int status = mIsysReceiverSubDev->SubscribeEvent(V4L2_EVENT_FRAME_SYNC); |
| CheckError(status != OK, status, "%s: Failed to subscribe sync event 0", __func__); |
| LOG1("%s: Using SOF event id 0 for sync", __func__); |
| |
| return OK; |
| } |
| |
| int SofSource::deinitDev() |
| { |
| if (mIsysReceiverSubDev == nullptr) return OK; |
| |
| int status = 0; |
| status = mIsysReceiverSubDev->UnsubscribeEvent(V4L2_EVENT_FRAME_SYNC); |
| if (status == OK) { |
| LOG1("%s: Unsubscribe SOF event id 0 done", __func__); |
| } else { |
| LOGE("%s: Failed to unsubscribe SOF event 0, status: %d", __func__, status); |
| } |
| |
| return status; |
| } |
| |
| int SofSource::configure() |
| { |
| if (mSofDisabled) { |
| return OK; |
| } |
| |
| return initDev(); |
| } |
| |
| int SofSource::start() |
| { |
| LOG1("%s", __func__); |
| if (mSofDisabled) { |
| return OK; |
| } |
| |
| int status = mPollThread->run("SofSource", PRIORITY_URGENT_AUDIO); |
| mExitPending = false; |
| return status; |
| |
| } |
| |
| int SofSource::stop() |
| { |
| LOG1("%s", __func__); |
| if (mSofDisabled) { |
| return OK; |
| } |
| |
| mExitPending = true; |
| int status = mPollThread->requestExitAndWait(); |
| return status; |
| |
| } |
| |
| int SofSource::poll() |
| { |
| int ret = 0; |
| const int pollTimeoutCount = 10; |
| const int pollTimeout = 1000; |
| |
| std::vector<V4L2Device*> pollDevs; |
| pollDevs.push_back(mIsysReceiverSubDev); |
| V4L2DevicePoller poller {pollDevs, -1}; |
| |
| std::vector<V4L2Device*> readyDevices; |
| |
| LOG2("@%s", __func__); |
| |
| int timeOutCount = pollTimeoutCount; |
| |
| while (timeOutCount-- && ret == 0) { |
| |
| ret = poller.Poll(pollTimeout, POLLPRI | POLLIN | POLLOUT | POLLERR, &readyDevices); |
| |
| if (ret == 0 && mExitPending) { |
| //timed out |
| LOGD("@%s: Timedout or thread is not running, ret = %d", __func__, ret); |
| return BAD_VALUE; |
| } |
| } |
| |
| //handle the poll error |
| if (ret < 0) { |
| if (mExitPending) { |
| //Exiting, no error |
| return 0; |
| } |
| |
| LOGE("%s: Poll error", __func__); |
| return ret; |
| } else if (ret == 0) { |
| LOGD("@%s, Sof poll timeout.", __func__); |
| return 0; |
| } |
| |
| struct v4l2_event event; |
| CLEAR(event); |
| mIsysReceiverSubDev->DequeueEvent(&event); |
| |
| EventDataSync syncData; |
| syncData.sequence = event.u.frame_sync.frame_sequence; |
| syncData.timestamp.tv_sec = event.timestamp.tv_sec; |
| syncData.timestamp.tv_usec = (event.timestamp.tv_nsec / 1000); |
| LOG2("%s:sof event sequence %ld, event.id %u", __func__, syncData.sequence, event.id); |
| TRACE_LOG_POINT("SofSource", "receive sof event", MAKE_COLOR(syncData.sequence), |
| syncData.sequence); |
| EventData eventData; |
| eventData.type = EVENT_ISYS_SOF; |
| eventData.buffer = nullptr; |
| eventData.data.sync = syncData; |
| notifyListeners(eventData); |
| |
| return 0; |
| } |
| |
| } |