/*
|
* 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 <stdlib.h>
|
#include <fcntl.h>
|
#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"
|
namespace RkCam {
|
|
const int RkPollThread::default_poll_timeout = 300; // 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",
|
};
|
|
RkPollThread::RkPollThread (const char* thName, int type, SmartPtr<V4l2Device> dev, RKStream *stream)
|
:Thread(thName)
|
,_poll_callback (NULL)
|
,frameid (0)
|
,_dev(dev)
|
,_stream(stream)
|
,_dev_type(type)
|
{
|
_poll_stop_fd[0] = -1;
|
_poll_stop_fd[1] = -1;
|
|
XCAM_LOG_DEBUG ("RkPollThread constructed");
|
}
|
|
RkPollThread::RkPollThread (const char* thName, int type, SmartPtr<V4l2SubDevice> dev, RKStream *stream)
|
:Thread(thName)
|
,_poll_callback (NULL)
|
,frameid (0)
|
,_subdev(dev)
|
,_stream(stream)
|
,_dev_type(type)
|
{
|
_poll_stop_fd[0] = -1;
|
_poll_stop_fd[1] = -1;
|
|
XCAM_LOG_DEBUG ("RkPollThread constructed");
|
}
|
|
RkPollThread::~RkPollThread ()
|
{
|
stop();
|
XCAM_LOG_DEBUG ("~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 ()
|
{
|
XCAM_LOG_DEBUG ("RkPollThread stop");
|
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 ();
|
|
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<V4l2Buffer> 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) {
|
XCAM_LOG_DEBUG ("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());
|
|
if (_dev_type == ISP_POLL_TX || _dev_type == ISP_POLL_RX) {
|
SmartPtr<V4l2BufferProxy> 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 {
|
SmartPtr<VideoBuffer> 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<V4l2SubDevice> dev, RKStream *stream)
|
:RkPollThread(thName, type, dev, stream)
|
{
|
XCAM_LOG_DEBUG ("RkEventPollThread constructed");
|
}
|
|
RkEventPollThread::~RkEventPollThread ()
|
{
|
stop();
|
XCAM_LOG_DEBUG ("~RkEventPollThread destructed");
|
}
|
|
XCamReturn
|
RkEventPollThread::poll_event_loop ()
|
{
|
XCamReturn ret = XCAM_RETURN_NO_ERROR;
|
int poll_ret = 0;
|
struct v4l2_event event;
|
int stop_fd = -1;
|
|
stop_fd = _poll_stop_fd[0];
|
poll_ret = _subdev->poll_event (RkPollThread::default_poll_timeout, stop_fd);
|
|
if (poll_ret == POLL_STOP_RET) {
|
XCAM_LOG_DEBUG ("poll event 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_WARNING ("poll event timeout and continue");
|
return XCAM_RETURN_ERROR_TIMEOUT;
|
}
|
xcam_mem_clear (event);
|
|
ret = _subdev->dequeue_event (event);
|
if (ret != XCAM_RETURN_NO_ERROR) {
|
XCAM_LOG_WARNING ("dequeue event failed on dev:%s", XCAM_STR(_subdev->get_device_name()));
|
return XCAM_RETURN_ERROR_IOCTL;
|
}
|
|
if (_poll_callback) {
|
SmartPtr<VideoBuffer> video_buf = _stream->new_video_buffer(event, _subdev);
|
_poll_callback->poll_buffer_ready (video_buf);
|
}
|
|
|
return ret;
|
}
|
|
RKStream::RKStream (SmartPtr<V4l2Device> dev, int type)
|
:_dev(dev)
|
,_dev_type(type)
|
,_dev_prepared(false)
|
{
|
_poll_thread = new RkPollThread(RKStream::poll_type_to_str[type], type, dev, this);
|
XCAM_LOG_DEBUG ("RKStream constructed");
|
}
|
|
RKStream::RKStream (SmartPtr<V4l2SubDevice> dev, int type)
|
:_subdev(dev)
|
,_dev_type(type)
|
,_dev_prepared(false)
|
{
|
_poll_thread = new RkEventPollThread(RKStream::poll_type_to_str[type], type, dev, this);
|
XCAM_LOG_DEBUG ("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);
|
XCAM_LOG_DEBUG ("RKStream constructed");
|
}
|
|
RKStream::~RKStream()
|
{
|
XCAM_LOG_DEBUG ("~RKStream destructed");
|
}
|
|
void
|
RKStream::start()
|
{
|
if (!_dev->is_activated())
|
_dev->start(_dev_prepared);
|
_poll_thread->start();
|
}
|
|
void
|
RKStream::startThreadOnly()
|
{
|
_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<VideoBuffer> RKStream::new_video_buffer(SmartPtr<V4l2Buffer> buf,
|
SmartPtr<V4l2Device> dev)
|
{
|
SmartPtr<VideoBuffer> 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<V4l2Device> dev, int type)
|
:RKStream(dev, type)
|
{
|
XCAM_LOG_DEBUG ("RKStream constructed");
|
}
|
|
//RKStatsStream::RKStatsStream (const char *name, int type)
|
// :RKStream(name, type)
|
//{
|
// XCAM_LOG_DEBUG ("RKStream constructed");
|
//}
|
|
RKStatsStream::~RKStatsStream()
|
{
|
XCAM_LOG_DEBUG ("~RKStream destructed");
|
}
|
|
bool RKStatsStream::set_event_handle_dev(SmartPtr<BaseSensorHw> &dev)
|
{
|
_event_handle_dev = dev;
|
return true;
|
}
|
|
bool RKStatsStream::set_iris_handle_dev(SmartPtr<LensHw> &dev)
|
{
|
_iris_handle_dev = dev;
|
return true;
|
}
|
|
bool RKStatsStream::set_focus_handle_dev(SmartPtr<LensHw> &dev)
|
{
|
_focus_handle_dev = dev;
|
return true;
|
}
|
|
bool RKStatsStream::set_rx_handle_dev(CamHwIsp20* dev)
|
{
|
_rx_handle_dev = dev;
|
return true;
|
}
|
|
SmartPtr<VideoBuffer>
|
RKStatsStream::new_video_buffer(SmartPtr<V4l2Buffer> buf,
|
SmartPtr<V4l2Device> dev)
|
{
|
ENTER_CAMHW_FUNCTION();
|
//SmartPtr<VideoBuffer> video_buf = nullptr;
|
SmartPtr<Isp20StatsBuffer> isp20stats_buf = nullptr;
|
|
// SmartPtr<RkAiqIspParamsProxy> ispParams = nullptr;
|
rkisp_effect_params_v20 ispParams = {0};
|
SmartPtr<RkAiqExpParamsProxy> expParams = nullptr;
|
SmartPtr<RkAiqIrisParamsProxy> irisParams = nullptr;
|
SmartPtr<RkAiqAfInfoProxy> 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;
|
isp20stats_buf->getEffectiveIspParams(buf->get_buf().sequence, ispParams);
|
isp20stats_buf->getEffectiveExpParams(buf->get_buf().sequence, expParams);
|
CaptureRawData::getInstance().save_metadata_and_register(buf->get_buf().sequence, ispParams, expParams, afParams, _rx_handle_dev->get_workingg_mode());
|
|
EXIT_CAMHW_FUNCTION();
|
|
return isp20stats_buf;
|
}
|
|
/*--------------------sof event stream---------------------------*/
|
|
RKSofEventStream::RKSofEventStream (SmartPtr<V4l2SubDevice> dev, int type)
|
:RKStream(dev, type)
|
{
|
XCAM_LOG_DEBUG ("RKSofEventStream constructed");
|
}
|
|
//RKSofEventStream::RKSofEventStream (const char *name, int type)
|
// :RKStream(name, type)
|
//{
|
// XCAM_LOG_DEBUG ("RKSofEventStream constructed");
|
//}
|
|
RKSofEventStream::~RKSofEventStream()
|
{
|
XCAM_LOG_DEBUG ("~RKSofEventStream destructed");
|
}
|
|
void
|
RKSofEventStream::start()
|
{
|
_subdev->start(_dev_prepared);
|
_subdev->subscribe_event(V4L2_EVENT_FRAME_SYNC);
|
_poll_thread->start();
|
}
|
|
void
|
RKSofEventStream::stop()
|
{
|
_poll_thread->stop();
|
_subdev->unsubscribe_event(V4L2_EVENT_FRAME_SYNC);
|
_subdev->stop();
|
}
|
|
SmartPtr<VideoBuffer>
|
RKSofEventStream::new_video_buffer(struct v4l2_event &event,
|
SmartPtr<V4l2Device> dev)
|
{
|
ENTER_CAMHW_FUNCTION();
|
SmartPtr<VideoBuffer> 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<SofEventData> evtdata = new SofEventData();
|
evtdata->_timestamp = tv_sec * 1000 * 1000 * 1000 + tv_nsec;
|
evtdata->_frameid = exp_id;
|
|
video_buf = new SofEventBuffer(evtdata, dev);
|
video_buf->_buf_type = _dev_type;
|
EXIT_CAMHW_FUNCTION();
|
|
return video_buf;
|
}
|
|
/*--------------------Output stream---------------------------*/
|
|
RKRawStream::RKRawStream (SmartPtr<V4l2Device> dev, int index, int type)
|
:RKStream(dev, type)
|
,_dev_index(index)
|
{
|
XCAM_LOG_DEBUG ("RKRawStream constructed");
|
}
|
|
RKRawStream::~RKRawStream()
|
{
|
XCAM_LOG_DEBUG ("~RKRawStream destructed");
|
}
|
|
SmartPtr<V4l2BufferProxy>
|
RKRawStream::new_v4l2proxy_buffer(SmartPtr<V4l2Buffer> buf,
|
SmartPtr<V4l2Device> dev)
|
{
|
ENTER_CAMHW_FUNCTION();
|
SmartPtr<V4l2BufferProxy> buf_proxy = new V4l2BufferProxy(buf, dev);
|
buf_proxy->_buf_type = _dev_type;
|
EXIT_CAMHW_FUNCTION();
|
|
return buf_proxy;
|
}
|
|
}; //namspace RkCam
|