/* * Copyright (c) 2019 Rockchip 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. * */ #include #include #include "Stream.h" #include "Isp20StatsBuffer.h" #include "rkisp2-config.h" #include "SensorHw.h" #include "LensHw.h" #include "Isp20_module_dbg.h" #include "CamHwIsp20.h" #include "CaptureRawData.h" #include "rkcif-config.h" namespace RkCam { const int RkPollThread::default_poll_timeout = -1; // ms const char* RKStream::poll_type_to_str[ISP_POLL_POST_MAX] = { "luma_poll", "isp_3a_stats_poll", "isp_param_poll", "ispp_fec_param_poll", "ispp_tnr_param_poll", "ispp_nr_param_poll", "ispp_tnr_stats_poll", "ispp_nr_stats_poll", "isp_sof_poll", "isp_tx_poll", "isp_rx_poll", "isp_sp_poll", "isp_pdaf_poll", "isp_gain", "isp_nr_img", "ispp_gain_kg", "ispp_gain_wr", "isp_stream_sync_poll", "vicap_stream_on_evt", "vicap_reset_evt", "vicap_with_rk1608_reset_evt", "vicap_scale_poll", }; RkPollThread::RkPollThread (const char* thName, int type, SmartPtr dev, RKStream *stream) :Thread(thName) ,_dev(dev) ,_subdev(NULL) ,_poll_callback (NULL) ,_stream(stream) ,frameid (0) ,_dev_type(type) { _poll_stop_fd[0] = -1; _poll_stop_fd[1] = -1; LOGD_CAMHW_SUBM(ISP20HW_SUBM, "RkPollThread constructed"); } RkPollThread::RkPollThread (const char* thName, int type, SmartPtr dev, RKStream *stream) :Thread(thName) ,_dev(dev) ,_subdev(dev) ,_poll_callback (NULL) ,_stream(stream) ,frameid (0) ,_dev_type(type) { _poll_stop_fd[0] = -1; _poll_stop_fd[1] = -1; LOGD_CAMHW_SUBM(ISP20HW_SUBM, "RkPollThread constructed"); } RkPollThread::~RkPollThread () { stop(); LOGD_CAMHW_SUBM(ISP20HW_SUBM, "~RkPollThread destructed"); } void RkPollThread::destroy_stop_fds () { if (_poll_stop_fd[1] != -1 || _poll_stop_fd[0] != -1) { close(_poll_stop_fd[0]); close(_poll_stop_fd[1]); _poll_stop_fd[0] = -1; _poll_stop_fd[1] = -1; } } XCamReturn RkPollThread::create_stop_fds () { int status = 0; XCamReturn ret = XCAM_RETURN_NO_ERROR; destroy_stop_fds (); status = pipe(_poll_stop_fd); if (status < 0) { XCAM_LOG_ERROR ("Failed to create ispp poll stop pipe: %s", strerror(errno)); ret = XCAM_RETURN_ERROR_UNKNOWN; goto exit_error; } /** * make the reading end of the pipe non blocking. * This helps during flush to read any information left there without * blocking */ status = fcntl(_poll_stop_fd[0], F_SETFL, O_NONBLOCK); if (status < 0) { XCAM_LOG_ERROR ("Fail to set event ispp stop pipe flag: %s", strerror(errno)); ret = XCAM_RETURN_ERROR_UNKNOWN; goto exit_error; } return XCAM_RETURN_NO_ERROR; exit_error: destroy_stop_fds (); return ret; } XCamReturn RkPollThread::start () { if (create_stop_fds ()) { XCAM_LOG_ERROR("create stop fds failed !"); return XCAM_RETURN_ERROR_UNKNOWN; } Thread::start(); return XCAM_RETURN_NO_ERROR; } XCamReturn RkPollThread::stop () { LOGI_CAMHW_SUBM(ISP20HW_SUBM, "RkPollThread %s:%s stop", get_name(), _dev.ptr() ? _dev->get_device_name() : _subdev.ptr() ? _subdev->get_device_name() : "null"); if (_poll_stop_fd[1] != -1) { char buf = 0xf; // random value to write to flush fd. unsigned int size = write(_poll_stop_fd[1], &buf, sizeof(char)); if (size != sizeof(char)) { XCAM_LOG_WARNING("Flush write not completed"); } } Thread::stop(); destroy_stop_fds (); LOGI_CAMHW_SUBM(ISP20HW_SUBM, "stop done"); return XCAM_RETURN_NO_ERROR; } bool RkPollThread::setPollCallback (PollCallback *callback) { //XCAM_ASSERT (!_poll_callback); _poll_callback = callback; return true; } XCamReturn RkPollThread::poll_buffer_loop () { XCamReturn ret = XCAM_RETURN_NO_ERROR; int poll_ret = 0; SmartPtr buf; int stop_fd = -1; stop_fd = _poll_stop_fd[0]; poll_ret = _dev->poll_event (RkPollThread::default_poll_timeout, stop_fd); if (poll_ret == POLL_STOP_RET) { LOGD_CAMHW_SUBM(ISP20HW_SUBM, "poll buffer stop success !"); // stop success, return error to stop the poll thread return XCAM_RETURN_ERROR_UNKNOWN; } if (poll_ret < 0 && (errno == EAGAIN || errno == EINTR)) { XCAM_LOG_DEBUG("poll buffer event got interrupt(0x%x), continue\n", poll_ret); return XCAM_RETURN_ERROR_TIMEOUT; } else if (poll_ret < 0) { XCAM_LOG_DEBUG("poll buffer event got error(0x%x) exit\n", poll_ret); return XCAM_RETURN_ERROR_UNKNOWN; } else if (poll_ret == 0) { XCAM_LOG_DEBUG("poll buffer event timeout(0x%x), continue\n", poll_ret); return XCAM_RETURN_ERROR_TIMEOUT; } ret = _dev->dequeue_buffer (buf); if (ret != XCAM_RETURN_NO_ERROR) { XCAM_LOG_WARNING ("dequeue buffer failed"); return ret; } XCAM_ASSERT (buf.ptr()); LOGD_CAMHW_SUBM(ISP20HW_SUBM, "camId: %d, frameId: %d: dequeue buffer on %s\n", mCamPhyId, buf->get_buf().sequence, RKStream::poll_type_to_str[_dev_type]); if (_dev_type == ISP_POLL_TX || _dev_type == ISP_POLL_RX) { SmartPtr buf_proxy = _stream->new_v4l2proxy_buffer(buf, _dev); if (_poll_callback && buf_proxy.ptr()) _poll_callback->poll_buffer_ready (buf_proxy, ((RKRawStream*)_stream)->_dev_index); } else if (_dev_type == ISP_POLL_PDAF_STATS) { SmartPtr buf_proxy = _stream->new_v4l2proxy_buffer(buf, _dev); if (_poll_callback && buf_proxy.ptr()) _poll_callback->poll_buffer_ready (buf_proxy, 0); } else { SmartPtr video_buf = _stream->new_video_buffer(buf, _dev); if (_poll_callback && video_buf.ptr()) _poll_callback->poll_buffer_ready (video_buf); } return ret; } RkEventPollThread::RkEventPollThread (const char* thName, int type, SmartPtr dev, RKStream *stream) :RkPollThread(thName, type, dev, stream) { LOGD_CAMHW_SUBM(ISP20HW_SUBM, "RkEventPollThread constructed"); } RkEventPollThread::RkEventPollThread (const char* thName, int type, SmartPtr subdev, RKStream *stream) :RkPollThread(thName, type, subdev, stream) { LOGD_CAMHW_SUBM(ISP20HW_SUBM, "RkEventPollThread constructed"); } RkEventPollThread::~RkEventPollThread () { stop(); LOGD_CAMHW_SUBM(ISP20HW_SUBM, "~RkEventPollThread destructed"); } XCamReturn RkEventPollThread::poll_event_loop () { XCamReturn ret = XCAM_RETURN_NO_ERROR; int poll_ret = 0; int stop_fd = -1; stop_fd = _poll_stop_fd[0]; poll_ret = _dev->poll_event (RkPollThread::default_poll_timeout, stop_fd); if (poll_ret == POLL_STOP_RET) { LOGI_CAMHW_SUBM(ISP20HW_SUBM, "%s: poll event stop success !", get_name()); // stop success, return error to stop the poll thread return XCAM_RETURN_ERROR_UNKNOWN; } if (poll_ret < 0 && (errno == EAGAIN || errno == EINTR)) { XCAM_LOG_DEBUG("poll buffer event got interrupt(0x%x), continue\n", poll_ret); return XCAM_RETURN_ERROR_TIMEOUT; } else if (poll_ret < 0) { XCAM_LOG_DEBUG("poll buffer event got error(0x%x) exit\n", poll_ret); return XCAM_RETURN_ERROR_UNKNOWN; } else if (poll_ret == 0) { XCAM_LOG_WARNING ("poll event timeout and continue"); return XCAM_RETURN_ERROR_TIMEOUT; } xcam_mem_clear (_event); ret = _dev->dequeue_event (_event); if (ret != XCAM_RETURN_NO_ERROR) { XCAM_LOG_WARNING ("dequeue event failed on dev:%s", XCAM_STR(_dev->get_device_name())); return XCAM_RETURN_ERROR_IOCTL; } LOGD_CAMHW_SUBM(ISP20HW_SUBM, "camId: %d, frameId: %d: dequeue the type(%d) of event on dev: %s", mCamPhyId, _event.u.frame_sync.frame_sequence, _event.type, XCAM_STR(_dev->get_device_name())); if (_poll_callback && _stream) { SmartPtr video_buf = _stream->new_video_buffer(_event, _subdev); _poll_callback->poll_buffer_ready (video_buf); } return ret; } /*--------------------ISP evt poll ---------------------------*/ XCamReturn RkStreamEventPollThread::poll_event_loop () { XCamReturn ret = RkEventPollThread::poll_event_loop(); if (ret == XCAM_RETURN_NO_ERROR) { if (_event.type == CIFISP_V4L2_EVENT_STREAM_START) { LOGI_CAMHW_SUBM(ISP20HW_SUBM, "%s: poll stream on evt success", _dev->get_device_name()); _pIsp->notify_isp_stream_status(true); } else if (_event.type == CIFISP_V4L2_EVENT_STREAM_STOP) { LOGI_CAMHW_SUBM(ISP20HW_SUBM, "%s: poll stream off evt success", _dev->get_device_name()); _pIsp->notify_isp_stream_status(false); // quit loop emit_stop (); return XCAM_RETURN_ERROR_UNKNOWN; } } return ret; } XCamReturn RkStreamEventPollThread::start() { XCamReturn ret = XCAM_RETURN_NO_ERROR; ret = _dev->open(false); if (ret) { return ret; } _dev->subscribe_event(CIFISP_V4L2_EVENT_STREAM_START); _dev->subscribe_event(CIFISP_V4L2_EVENT_STREAM_STOP); return RkEventPollThread::start(); } XCamReturn RkStreamEventPollThread::stop () { XCamReturn ret = XCAM_RETURN_NO_ERROR; ret = RkEventPollThread::stop(); if (_dev->is_opened()) { _dev->unsubscribe_event(CIFISP_V4L2_EVENT_STREAM_START); _dev->unsubscribe_event(CIFISP_V4L2_EVENT_STREAM_STOP); ret = _dev->close(); } return ret; } RKStream::RKStream (SmartPtr dev, int type) :_dev(dev) ,_dev_type(type) ,_dev_prepared(false) { _poll_thread = new RkPollThread(RKStream::poll_type_to_str[type], type, dev, this); LOGD_CAMHW_SUBM(ISP20HW_SUBM, "RKStream constructed"); } RKStream::RKStream (SmartPtr dev, int type) :_subdev(dev) ,_dev_type(type) ,_dev_prepared(false) { _poll_thread = new RkEventPollThread(RKStream::poll_type_to_str[type], type, dev, this); LOGD_CAMHW_SUBM(ISP20HW_SUBM, "RKStream constructed"); } RKStream::RKStream (const char *path, int type) :_dev_type(type) ,_dev_prepared(false) { _dev = new V4l2Device(path); _poll_thread = new RkPollThread(RKStream::poll_type_to_str[type], type, _dev, this); LOGD_CAMHW_SUBM(ISP20HW_SUBM, "RKStream constructed"); } RKStream::~RKStream() { LOGD_CAMHW_SUBM(ISP20HW_SUBM, "~RKStream destructed"); } void RKStream::start() { if (!_dev->is_activated()) _dev->start(_dev_prepared); _poll_thread->setCamPhyId(mCamPhyId); if (_dev_type == ISP_POLL_3A_STATS || \ _dev_type == ISP_POLL_TX || \ _dev_type == ISP_POLL_RX) { _poll_thread->set_policy(SCHED_RR); _poll_thread->set_priority(20); } _poll_thread->start(); } void RKStream::startThreadOnly() { _poll_thread->setCamPhyId(mCamPhyId); if (_dev_type == ISP_POLL_3A_STATS || \ _dev_type == ISP_POLL_TX || \ _dev_type == ISP_POLL_RX) { _poll_thread->set_policy(SCHED_RR); _poll_thread->set_priority(20); } _poll_thread->start(); } void RKStream::startDeviceOnly() { if (!_dev->is_activated()) _dev->start(_dev_prepared); } void RKStream::stop() { _poll_thread->stop(); _dev->stop(); _dev_prepared = false; } void RKStream::stopThreadOnly() { _poll_thread->stop(); } void RKStream::stopDeviceOnly() { _dev->stop(); _dev_prepared = false; } void RKStream::pause() { } void RKStream::resume() { } void RKStream::set_device_prepared(bool prepare) { _dev_prepared = prepare; } SmartPtr RKStream::new_video_buffer(SmartPtr buf, SmartPtr dev) { SmartPtr video_buf = new V4l2BufferProxy (buf, dev); video_buf->_buf_type = _dev_type; return video_buf; } bool RKStream::setPollCallback (PollCallback *callback) { return _poll_thread->setPollCallback(callback); } XCamReturn RKStream::getFormat(struct v4l2_format &format) { return _dev->get_format (format); } XCamReturn RKStream::getFormat(struct v4l2_subdev_format &format) { return _subdev->getFormat (format); } RKStatsStream::RKStatsStream (SmartPtr dev, int type) :RKStream(dev, type) { LOGD_CAMHW_SUBM(ISP20HW_SUBM, "RKStream constructed"); } //RKStatsStream::RKStatsStream (const char *name, int type) // :RKStream(name, type) //{ // LOGD_CAMHW_SUBM(ISP20HW_SUBM, "RKStream constructed"); //} RKStatsStream::~RKStatsStream() { LOGD_CAMHW_SUBM(ISP20HW_SUBM, "~RKStream destructed"); } bool RKStatsStream::set_event_handle_dev(SmartPtr &dev) { _event_handle_dev = dev; return true; } bool RKStatsStream::set_iris_handle_dev(SmartPtr &dev) { _iris_handle_dev = dev; return true; } bool RKStatsStream::set_focus_handle_dev(SmartPtr &dev) { _focus_handle_dev = dev; return true; } bool RKStatsStream::set_rx_handle_dev(CamHwIsp20* dev) { _rx_handle_dev = dev; return true; } SmartPtr RKStatsStream::new_video_buffer(SmartPtr buf, SmartPtr dev) { ENTER_CAMHW_FUNCTION(); //SmartPtr video_buf = nullptr; SmartPtr isp20stats_buf = nullptr; SmartPtr irisParams = nullptr; SmartPtr afParams = nullptr; if (_focus_handle_dev.ptr()) { _focus_handle_dev->getAfInfoParams(afParams, buf->get_buf().sequence); _focus_handle_dev->getIrisInfoParams(irisParams, buf->get_buf().sequence); } isp20stats_buf = new Isp20StatsBuffer(buf, dev, _event_handle_dev, _rx_handle_dev, afParams, irisParams); isp20stats_buf->_buf_type = _dev_type; EXIT_CAMHW_FUNCTION(); return isp20stats_buf; } /*--------------------sof event stream---------------------------*/ std::atomic RKSofEventStream::_is_subscribed{false}; RKSofEventStream::RKSofEventStream (SmartPtr dev, int type, bool linkedToRk1608) :RKStream(dev, type) { _linked_to_1608 = linkedToRk1608; LOGD_CAMHW_SUBM(ISP20HW_SUBM, "RKSofEventStream constructed"); } //RKSofEventStream::RKSofEventStream (const char *name, int type) // :RKStream(name, type) //{ // LOGD_CAMHW_SUBM(ISP20HW_SUBM, "RKSofEventStream constructed"); //} RKSofEventStream::~RKSofEventStream() { LOGD_CAMHW_SUBM(ISP20HW_SUBM, "~RKSofEventStream destructed"); } void RKSofEventStream::start() { _subdev->start(_dev_prepared); _poll_thread->setCamPhyId(mCamPhyId); _poll_thread->start(); _subdev->subscribe_event(V4L2_EVENT_FRAME_SYNC); if (_linked_to_1608) { if (!_is_subscribed.load()) { _subdev->subscribe_event(V4L2_EVENT_RESET_DEV); _is_subscribed.store(true); } } else { _subdev->subscribe_event(V4L2_EVENT_RESET_DEV); } } void RKSofEventStream::stop() { _poll_thread->stop(); _subdev->unsubscribe_event(V4L2_EVENT_FRAME_SYNC); if (_linked_to_1608) { if (_is_subscribed.load()) { _subdev->unsubscribe_event(V4L2_EVENT_RESET_DEV); _is_subscribed.store(false); } } else { _subdev->unsubscribe_event(V4L2_EVENT_RESET_DEV); } _subdev->stop(); } SmartPtr RKSofEventStream::new_video_buffer(struct v4l2_event &event, SmartPtr dev) { ENTER_CAMHW_FUNCTION(); SmartPtr video_buf = nullptr; int64_t tv_sec = event.timestamp.tv_sec; int64_t tv_nsec = event.timestamp.tv_nsec; int exp_id = event.u.frame_sync.frame_sequence; SmartPtr evtdata = new SofEventData(); evtdata->_timestamp = tv_sec * 1000 * 1000 * 1000 + tv_nsec; evtdata->_frameid = exp_id; video_buf = new SofEventBuffer(evtdata, dev); if (event.type == V4L2_EVENT_RESET_DEV) { if (_linked_to_1608) { video_buf->_buf_type = VICAP_WITH_RK1608_RESET_EVT; } else video_buf->_buf_type = VICAP_RESET_EVT; } else { video_buf->_buf_type = _dev_type; } video_buf->set_sequence (exp_id); EXIT_CAMHW_FUNCTION(); return video_buf; } /*--------------------Output stream---------------------------*/ RKRawStream::RKRawStream (SmartPtr dev, int index, int type) :RKStream(dev, type) ,_dev_index(index) { LOGD_CAMHW_SUBM(ISP20HW_SUBM, "RKRawStream constructed"); } RKRawStream::~RKRawStream() { LOGD_CAMHW_SUBM(ISP20HW_SUBM, "~RKRawStream destructed"); } SmartPtr RKRawStream::new_v4l2proxy_buffer(SmartPtr buf, SmartPtr dev) { ENTER_CAMHW_FUNCTION(); SmartPtr buf_proxy = new V4l2BufferProxy(buf, dev); buf_proxy->_buf_type = _dev_type; EXIT_CAMHW_FUNCTION(); return buf_proxy; } SmartPtr RKRawStream::new_video_buffer(SmartPtr buf, SmartPtr dev) { ENTER_CAMHW_FUNCTION(); buf->set_reserved((uintptr_t)_reserved); SmartPtr video_buf = new V4l2BufferProxy(buf, dev); video_buf->_buf_type = _dev_type; EXIT_CAMHW_FUNCTION(); return video_buf; } void RKRawStream::set_reserved_data(int bpp) { _bpp = bpp; _reserved[0] = _dev_index; _reserved[1] = bpp; } RKPdafStream::RKPdafStream (SmartPtr dev, int type) :RKStream(dev, type) { LOGD_CAMHW_SUBM(ISP20HW_SUBM, "RKRawStream constructed"); } RKPdafStream::~RKPdafStream() { LOGD_CAMHW_SUBM(ISP20HW_SUBM, "~RKRawStream destructed"); } SmartPtr RKPdafStream::new_v4l2proxy_buffer(SmartPtr buf, SmartPtr dev) { ENTER_CAMHW_FUNCTION(); SmartPtr buf_proxy = new PdafBufferProxy(buf, dev); buf_proxy->_buf_type = _dev_type; EXIT_CAMHW_FUNCTION(); return buf_proxy; } } //namspace RkCam