#include "CamHwIsp20.h"
|
#include "rk_aiq_comm.h"
|
|
namespace RkCam {
|
RawStreamCapUnit::RawStreamCapUnit ()
|
:_skip_num(0)
|
,_state(RAW_CAP_STATE_INVALID)
|
{
|
}
|
|
RawStreamCapUnit::RawStreamCapUnit (const rk_sensor_full_info_t *s_info, bool linked_to_isp)
|
:_skip_num(0)
|
,_state(RAW_CAP_STATE_INVALID)
|
{
|
/*
|
* for _mipi_tx_devs, index 0 refer to short frame always, inedex 1 refer
|
* to middle frame always, index 2 refert to long frame always.
|
* for CIF usecase, because mipi_id0 refert to long frame always, so we
|
* should know the HDR mode firstly befor building the relationship between
|
* _mipi_tx_devs array and mipi_idx. here we just set the mipi_idx to
|
* _mipi_tx_devs, we will build the real relation in start.
|
* for CIF usecase, rawwr2_path is always connected to _mipi_tx_devs[0],
|
* rawwr0_path is always connected to _mipi_tx_devs[1], and rawwr1_path is always
|
* connected to _mipi_tx_devs[0]
|
*/
|
//short frame
|
if (strlen(s_info->isp_info->rawrd2_s_path)) {
|
if (linked_to_isp)
|
_dev[0] = new V4l2Device (s_info->isp_info->rawwr2_path);//rkisp_rawwr2
|
else {
|
if (s_info->dvp_itf) {
|
if (strlen(s_info->cif_info->stream_cif_path))
|
_dev[0] = new V4l2Device (s_info->cif_info->stream_cif_path);
|
else
|
_dev[0] = new V4l2Device (s_info->cif_info->dvp_id0);
|
} else
|
_dev[0] = new V4l2Device (s_info->cif_info->mipi_id0);
|
}
|
_dev[0]->open();
|
}
|
//mid frame
|
if (strlen(s_info->isp_info->rawrd0_m_path)) {
|
if (linked_to_isp)
|
_dev[1] = new V4l2Device (s_info->isp_info->rawwr0_path);//rkisp_rawwr0
|
else {
|
if (!s_info->dvp_itf)
|
_dev[1] = new V4l2Device (s_info->cif_info->mipi_id1);
|
}
|
|
if (_dev[1].ptr())
|
_dev[1]->open();
|
}
|
//long frame
|
if (strlen(s_info->isp_info->rawrd1_l_path)) {
|
if (linked_to_isp)
|
_dev[2] = new V4l2Device (s_info->isp_info->rawwr1_path);//rkisp_rawwr1
|
else {
|
if (!s_info->dvp_itf)
|
_dev[2] = new V4l2Device (s_info->cif_info->mipi_id2);//rkisp_rawwr1
|
}
|
if (_dev[2].ptr())
|
_dev[2]->open();
|
}
|
for (int i = 0; i < 3; i++) {
|
if (linked_to_isp) {
|
if (_dev[i].ptr())
|
_dev[i]->set_buffer_count(ISP_TX_BUF_NUM);
|
} else {
|
if (_dev[i].ptr())
|
_dev[i]->set_buffer_count(VIPCAP_TX_BUF_NUM);
|
}
|
if (_dev[i].ptr())
|
_dev[i]->set_buf_sync (true);
|
|
_dev_bakup[i] = _dev[i];
|
_dev_index[i] = i;
|
_stream[i] = new RKRawStream(_dev[i], i, ISP_POLL_TX);
|
_stream[i]->setPollCallback(this);
|
}
|
_state = RAW_CAP_STATE_INITED;
|
}
|
|
RawStreamCapUnit::~RawStreamCapUnit ()
|
{
|
_state = RAW_CAP_STATE_INVALID;
|
}
|
|
XCamReturn RawStreamCapUnit::start(int mode)
|
{
|
LOGD( "%s enter", __FUNCTION__);
|
for (int i = 0; i < _mipi_dev_max; i++) {
|
_stream[i]->start();
|
}
|
_state = RAW_CAP_STATE_STARTED;
|
LOGD( "%s exit", __FUNCTION__);
|
return XCAM_RETURN_NO_ERROR;
|
}
|
|
XCamReturn RawStreamCapUnit::stop ()
|
{
|
LOGD( "%s enter", __FUNCTION__);
|
for (int i = 0; i < _mipi_dev_max; i++) {
|
_stream[i]->stopThreadOnly();
|
}
|
_buf_mutex.lock();
|
for (int i = 0; i < _mipi_dev_max; i++) {
|
buf_list[i].clear ();
|
}
|
_buf_mutex.unlock();
|
for (int i = 0; i < _mipi_dev_max; i++) {
|
_stream[i]->stopDeviceOnly();
|
}
|
_state = RAW_CAP_STATE_STOPPED;
|
LOGD( "%s exit", __FUNCTION__);
|
return XCAM_RETURN_NO_ERROR;
|
}
|
|
XCamReturn
|
RawStreamCapUnit::prepare(int idx)
|
{
|
XCamReturn ret = XCAM_RETURN_NO_ERROR;
|
LOGD( "%s enter", __FUNCTION__);
|
// mipi rx/tx format should match to sensor.
|
for (int i = 0; i < 3; i++) {
|
if (!(idx & (1 << i)))
|
continue;
|
ret = _dev[i]->prepare();
|
if (ret < 0)
|
LOGE( "mipi tx:%d prepare err: %d\n", ret);
|
|
_stream[i]->set_device_prepared(true);
|
}
|
_state = RAW_CAP_STATE_PREPARED;
|
LOGD( "%s exit", __FUNCTION__);
|
return ret;
|
}
|
|
void
|
RawStreamCapUnit::prepare_cif_mipi()
|
{
|
LOGD( "%s enter,working_mode=0x%x", __FUNCTION__, _working_mode);
|
|
SmartPtr<V4l2Device> tx_devs_tmp[3] =
|
{
|
_dev_bakup[0],
|
_dev_bakup[1],
|
_dev_bakup[2],
|
};
|
|
// _mipi_tx_devs
|
if (_working_mode == RK_AIQ_WORKING_MODE_NORMAL) {
|
// use _mipi_tx_devs[0] only
|
// id0 as normal
|
// do nothing
|
LOGD( "CIF tx: %s -> normal",
|
_dev[0]->get_device_name());
|
} else if (RK_AIQ_HDR_GET_WORKING_MODE(_working_mode) == RK_AIQ_WORKING_MODE_ISP_HDR2) {
|
// use _mipi_tx_devs[0] and _mipi_tx_devs[1]
|
// id0 as l, id1 as s
|
SmartPtr<V4l2Device> tmp = tx_devs_tmp[1];
|
tx_devs_tmp[1] = tx_devs_tmp[0];
|
tx_devs_tmp[0] = tmp;
|
LOGD( "CIF tx: %s -> long",
|
_dev[1]->get_device_name());
|
LOGD( "CIF tx: %s -> short",
|
_dev[0]->get_device_name());
|
} else if (RK_AIQ_HDR_GET_WORKING_MODE(_working_mode) == RK_AIQ_WORKING_MODE_ISP_HDR3) {
|
// use _mipi_tx_devs[0] and _mipi_tx_devs[1]
|
// id0 as l, id1 as m, id2 as s
|
SmartPtr<V4l2Device> tmp = tx_devs_tmp[2];
|
tx_devs_tmp[2] = tx_devs_tmp[0];
|
tx_devs_tmp[0] = tmp;
|
LOGD( "CIF tx: %s -> long",
|
_dev[2]->get_device_name());
|
LOGD( "CIF tx: %s -> middle",
|
_dev[1]->get_device_name());
|
LOGD( "CIF tx: %s -> short",
|
_dev[0]->get_device_name());
|
} else {
|
LOGE( "wrong hdr mode: %d\n", _working_mode);
|
}
|
for (int i = 0; i < 3; i++) {
|
_dev[i] = tx_devs_tmp[i];
|
_dev_index[i] = i;
|
_stream[i].release();
|
_stream[i] = new RKRawStream(_dev[i], i, ISP_POLL_TX);
|
_stream[i]->setPollCallback(this);
|
}
|
LOGD( "%s exit", __FUNCTION__);
|
}
|
|
void
|
RawStreamCapUnit::set_working_mode(int mode)
|
{
|
LOGD( "%s enter,mode=0x%x", __FUNCTION__, mode);
|
_working_mode = mode;
|
|
switch (_working_mode) {
|
case RK_AIQ_ISP_HDR_MODE_3_FRAME_HDR:
|
case RK_AIQ_ISP_HDR_MODE_3_LINE_HDR:
|
_mipi_dev_max = 3;
|
break;
|
case RK_AIQ_ISP_HDR_MODE_2_FRAME_HDR:
|
case RK_AIQ_ISP_HDR_MODE_2_LINE_HDR:
|
_mipi_dev_max = 2;
|
break;
|
default:
|
_mipi_dev_max = 1;
|
}
|
LOGD( "%s exit", __FUNCTION__);
|
}
|
|
void
|
RawStreamCapUnit::set_tx_devices(SmartPtr<V4l2Device> mipi_tx_devs[3])
|
{
|
for (int i = 0; i < 3; i++) {
|
_dev[i] = mipi_tx_devs[i];
|
}
|
}
|
|
SmartPtr<V4l2Device>
|
RawStreamCapUnit::get_tx_device(int index)
|
{
|
if (index > _mipi_dev_max)
|
return nullptr;
|
else
|
return _dev[index];
|
}
|
|
void
|
RawStreamCapUnit::set_tx_format(const struct v4l2_subdev_format& sns_sd_fmt, uint32_t sns_v4l_pix_fmt)
|
{
|
// set mipi tx,rx fmt
|
// for cif: same as sensor fmt
|
|
struct v4l2_format format;
|
memset(&format, 0, sizeof(format));
|
|
for (int i = 0; i < 3; i++) {
|
if (_dev[i].ptr())
|
_dev[i]->get_format (format);
|
if (format.fmt.pix.width != sns_sd_fmt.format.width ||
|
format.fmt.pix.height != sns_sd_fmt.format.height ||
|
format.fmt.pix.pixelformat != sns_v4l_pix_fmt) {
|
if (_dev[i].ptr())
|
_dev[i]->set_format(sns_sd_fmt.format.width,
|
sns_sd_fmt.format.height,
|
sns_v4l_pix_fmt,
|
V4L2_FIELD_NONE,
|
0);
|
}
|
}
|
_dev[0]->get_format (_format);
|
LOGD("set tx fmt info: fmt 0x%x, %dx%d !",
|
sns_v4l_pix_fmt, sns_sd_fmt.format.width, sns_sd_fmt.format.height);
|
}
|
|
void
|
RawStreamCapUnit::set_tx_format(const struct v4l2_subdev_selection& sns_sd_sel, uint32_t sns_v4l_pix_fmt)
|
{
|
// set mipi tx,rx fmt
|
// for cif: same as sensor fmt
|
|
struct v4l2_format format;
|
memset(&format, 0, sizeof(format));
|
|
for (int i = 0; i < 3; i++) {
|
if (_dev[i].ptr())
|
_dev[i]->get_format (format);
|
if (format.fmt.pix.width != sns_sd_sel.r.width ||
|
format.fmt.pix.height != sns_sd_sel.r.height ||
|
format.fmt.pix.pixelformat != sns_v4l_pix_fmt) {
|
if (_dev[i].ptr())
|
_dev[i]->set_format(sns_sd_sel.r.width,
|
sns_sd_sel.r.height,
|
sns_v4l_pix_fmt,
|
V4L2_FIELD_NONE,
|
0);
|
}
|
}
|
_dev[0]->get_format (_format);
|
LOGD("set tx fmt info: fmt 0x%x, %dx%d !",
|
sns_v4l_pix_fmt, sns_sd_sel.r.width, sns_sd_sel.r.height);
|
}
|
|
void
|
RawStreamCapUnit::set_devices(SmartPtr<V4l2SubDevice> ispdev, CamHwIsp20* handle, RawStreamProcUnit *proc)
|
{
|
_isp_core_dev = ispdev;
|
_camHw = handle;
|
_proc_stream = proc;
|
}
|
|
XCamReturn
|
RawStreamCapUnit::poll_buffer_ready (SmartPtr<V4l2BufferProxy> &buf, int dev_index)
|
{
|
XCamReturn ret = XCAM_RETURN_NO_ERROR;
|
SmartPtr<V4l2BufferProxy> buf_s, buf_m, buf_l;
|
|
_buf_mutex.lock();
|
buf_list[dev_index].push(buf);
|
ret = sync_raw_buf(buf_s, buf_m, buf_l);
|
_buf_mutex.unlock();
|
|
if (ret == XCAM_RETURN_NO_ERROR) {
|
if (_proc_stream)
|
_proc_stream->send_sync_buf(buf_s, buf_m, buf_l);
|
|
if (_camHw->mHwResLintener) {
|
struct VideoBufferInfo vbufInfo;
|
vbufInfo.init(_format.fmt.pix.pixelformat, _format.fmt.pix.width, _format.fmt.pix.height,
|
_format.fmt.pix.width, _format.fmt.pix.height, _format.fmt.pix.sizeimage, true);
|
SmartPtr<SubVideoBuffer> subvbuf = new SubVideoBuffer (buf_s);
|
subvbuf->_buf_type = ISP_POLL_TX;
|
subvbuf->set_sequence(buf_s->get_sequence());
|
subvbuf->set_video_info(vbufInfo);
|
SmartPtr<VideoBuffer> vbuf = subvbuf.dynamic_cast_ptr<VideoBuffer>();
|
_camHw->mHwResLintener->hwResCb(vbuf);
|
}
|
}
|
|
return XCAM_RETURN_NO_ERROR;
|
}
|
|
void RawStreamCapUnit::skip_frames(int skip_num, int32_t skip_seq)
|
{
|
_mipi_mutex.lock();
|
_skip_num = skip_num;
|
_skip_to_seq = skip_seq + _skip_num;
|
_mipi_mutex.unlock();
|
}
|
|
bool RawStreamCapUnit::check_skip_frame(int32_t buf_seq)
|
{
|
_mipi_mutex.lock();
|
#if 0 // ts
|
if (_skip_num > 0) {
|
int64_t skip_ts_ms = _skip_start_ts / 1000 / 1000;
|
int64_t buf_ts_ms = buf_ts / 1000;
|
LOGD( "skip num %d, start from %" PRId64 " ms, buf ts %" PRId64 " ms",
|
_skip_num,
|
skip_ts_ms,
|
buf_ts_ms);
|
if (buf_ts_ms > skip_ts_ms) {
|
_skip_num--;
|
_mipi_mutex.unlock();
|
return true;
|
}
|
}
|
#else
|
|
if ((_skip_num > 0) && (buf_seq < _skip_to_seq)) {
|
LOGE( "skip num %d, skip seq %d, dest seq %d",
|
_skip_num, buf_seq, _skip_to_seq);
|
_skip_num--;
|
_mipi_mutex.unlock();
|
return true;
|
}
|
#endif
|
_mipi_mutex.unlock();
|
return false;
|
}
|
|
XCamReturn
|
RawStreamCapUnit::sync_raw_buf
|
(
|
SmartPtr<V4l2BufferProxy> &buf_s,
|
SmartPtr<V4l2BufferProxy> &buf_m,
|
SmartPtr<V4l2BufferProxy> &buf_l
|
)
|
{
|
uint32_t sequence_s = -1, sequence_m = -1, sequence_l = -1;
|
|
for (int i = 0; i < _mipi_dev_max; i++) {
|
if (buf_list[i].is_empty()) {
|
return XCAM_RETURN_ERROR_FAILED;
|
}
|
}
|
|
buf_l = buf_list[ISP_MIPI_HDR_L].front();
|
if (buf_l.ptr())
|
sequence_l = buf_l->get_sequence();
|
|
buf_m = buf_list[ISP_MIPI_HDR_M].front();
|
if (buf_m.ptr())
|
sequence_m = buf_m->get_sequence();
|
|
buf_s = buf_list[ISP_MIPI_HDR_S].front();
|
|
if (buf_s.ptr()) {
|
sequence_s = buf_s->get_sequence();
|
if ((_working_mode == RK_AIQ_ISP_HDR_MODE_3_FRAME_HDR ||
|
_working_mode == RK_AIQ_ISP_HDR_MODE_3_LINE_HDR) &&
|
buf_m.ptr() && buf_l.ptr() && buf_s.ptr() &&
|
sequence_l == sequence_s && sequence_m == sequence_s) {
|
|
buf_list[ISP_MIPI_HDR_S].erase(buf_s);
|
buf_list[ISP_MIPI_HDR_M].erase(buf_m);
|
buf_list[ISP_MIPI_HDR_L].erase(buf_l);
|
if (check_skip_frame(sequence_s)) {
|
LOGW( "skip frame %d", sequence_s);
|
goto end;
|
}
|
} else if ((_working_mode == RK_AIQ_ISP_HDR_MODE_2_FRAME_HDR ||
|
_working_mode == RK_AIQ_ISP_HDR_MODE_2_LINE_HDR) &&
|
buf_m.ptr() && buf_s.ptr() && sequence_m == sequence_s) {
|
buf_list[ISP_MIPI_HDR_S].erase(buf_s);
|
buf_list[ISP_MIPI_HDR_M].erase(buf_m);
|
if (check_skip_frame(sequence_s)) {
|
LOGE( "skip frame %d", sequence_s);
|
goto end;
|
}
|
} else if (_working_mode == RK_AIQ_WORKING_MODE_NORMAL) {
|
buf_list[ISP_MIPI_HDR_S].erase(buf_s);
|
if (check_skip_frame(sequence_s)) {
|
LOGW( "skip frame %d", sequence_s);
|
goto end;
|
}
|
} else {
|
LOGW( "do nothing, sequence not match l: %d, s: %d, m: %d !!!",
|
sequence_l, sequence_s, sequence_m);
|
}
|
return XCAM_RETURN_NO_ERROR;
|
}
|
end:
|
return XCAM_RETURN_ERROR_FAILED;
|
}
|
|
}
|