I’m failing to get images from an imx290 sensor with nvcamera-daemon when v4l2-ctl works. This is our setup in the DTB for the video mode (the “use_sensor_mode_id” flag is set to “true”):
mode0 { // IMX290_MODE_1948x1108
mclk_khz = "25000";
num_lanes = "4";
tegra_sinterface = "serial_a";
discontinuous_clk = "yes";
dpcm_enable = "false";
cil_settletime = "0";
dynamic_pixel_bit_depth = "12";
/* kernel expects this setting */
pixel_t = "bayer_rggb12";
/* nvcamera-daemon expects these settings. */
csi_pixel_bit_depth = "12";
mode_type = "bayer";
pixel_phase = "rggb";
active_w = "1948"; // X_OUT_SIZE set-up in driver
active_h = "1096"; // Y_OUT_SIZE set-up in driver
readout_orientation = "0";
line_length = "4400"; // hmax set-up in driver for 30 FPS
gain_factor = "1";
framerate_factor = "1";
inherent_gain = "1";
mclk_multiplier = "6"; // must be larger than pixel_clock / mclk
pix_clk_hz = "148500000"; // 37.125 MHz * 4 Lanes
min_gain_val = "1"; // defined in imx290.c
max_gain_val = "31"; // defined in imx290.c
min_hdr_ratio = "1";
max_hdr_ratio = "64";
min_framerate = "30";
max_framerate = "30";
min_exp_time = "15"; // 4 line time (minimal 4 lines), in micro-second
max_exp_time = "236610";
embedded_metadata_height = "1"; // specific to the sensor
};
I have verified more than just once that the image sensor is set-up accordingly. In fact, v4l2-ctl captures images with exactly that geometry. Telling v4l2-ctl a different geometry leads to the correct errors: either PIXEL_SHORT_LINE, PIXEL_LONG_LINE, PIXEL_RUNAWAY or missing EOF. Here a working example:
v4l2-ctl --verbose --set-fmt-video=width=1948,height=1096,pixelformat=RG12 --stream-mmap --set-ctrl bypass_mode=0 --stream-count=100 -d /dev/video0
VIDIOC_QUERYCAP: ok
VIDIOC_S_EXT_CTRLS: ok
VIDIOC_G_FMT: ok
VIDIOC_S_FMT: ok
Format Video Capture:
Width/Height : 1948/1096
Pixel Format : 'RG12'
Field : None
Bytes per Line : 4096
Size Image : 4489216
Colorspace : sRGB
Transfer Function : Default
YCbCr/HSV Encoding: Default
Quantization : Default
Flags :
VIDIOC_REQBUFS: ok
VIDIOC_QUERYBUF: ok
VIDIOC_QBUF: ok
VIDIOC_QUERYBUF: ok
VIDIOC_QBUF: ok
VIDIOC_QUERYBUF: ok
VIDIOC_QBUF: ok
VIDIOC_QUERYBUF: ok
VIDIOC_QBUF: ok
VIDIOC_STREAMON: ok
Index : 0
Type : Video Capture
Flags : mapped, done
Field : None
Sequence : 0
Length : 4489216
Bytesused: 4489216
Timestamp: 2492.284220s (Monotonic, End-of-Frame)
...
It really captures 30 frames per second.
When I try to capture using nvcamera-daemon, everything appears to look OK. This is how it thinks to set-up VI/CSI:
apply:-----------------------
NvPclSettingsApply: Reading PCL settings
PowerServiceUtils:calculateReqClock: entered
PowerServiceHw:addRequest: table size: before: 0, after:1
request table for VI 0:
req[0]: guID=0, stageID=SensorCapture
req[0]: inW=1948, inH=1096, inBpp = 12, fps=30
req[0]: outW=1948, outH=1096, outBpp=12
req[0]: out1W=0, out1H=0, out1Bpp=0
req[0]: out2W=0, out2H=0, out2Bpp=0
req[0]: clock=25987500, pixelRate=148500000, timeout=900
req[0]: isoBw=311844, timeout=900
req[0]: non_isoBw=0, timeout=900
PowerServiceUtils:calculateReqClock: entered
PowerServiceHw:addRequest: table size: before: 0, after:1
request table for CSI 0:
req[0]: guID=0, stageID=SensorCapture
req[0]: inW=1948, inH=1096, inBpp = 12, fps=30
req[0]: outW=1948, outH=1096, outBpp=12
req[0]: out1W=0, out1H=0, out1Bpp=0
req[0]: out2W=0, out2H=0, out2Bpp=0
req[0]: clock=36196872, pixelRate=148500000, timeout=900
req[0]: isoBw=0, timeout=900
req[0]: non_isoBw=0, timeout=900
PowerServiceHwVi:setIso: m_bwVal_Iso=311844
PowerServiceHw:setClock: PowerServiceHw[1]: requested_clock_Hz=25987500
PowerServiceHw:setClock: PowerServiceHw[0]: requested_clock_Hz=36196872
PowerServiceCore:setCameraBw: totalIsoBw=311844
NvPclSettingsUpdate: Sending Updated Settings through PCL
NvPclSettingsApply: Applying last settings through PCL
apply:+++++++++++++++++++++++
Note that it says 1948x1096@30 as input parameters to the VI and the CSI. However, a little later the following line appears:
captureErrorCallback Stream 0.0 capture 1 failed: ts 2019813512544 frame 10 error 4 data 0x00000200
This error code means that the first valid pixel line (line #0) is too short. I’ve seen similar errors occur on other lines, but always in the first three ones.
I have confirmed that
- The image sensor outputs 30fps (by measuring the XVS pin frequency).
- The line length transmitted by the sensor is 1948 pixels (looked up the registers in the DS90UB954 deserializer between camera and imx290).
For further debugging, I have enabled the DS90UB954 test pattern generator with a geometry of 1948x1096 pixels. It also works fine with v4l2-ctl and fails with exactly the same error in nvcamera-daemon. I was playing a bit with the TPG geometry (which is far more flexible than the image sensor) and increased the generated line width until the PIXEL_SHORT_LINE error was gone. The following behaviour was observed:
- TPG line length == 1974 gives PIXEL_SHORT_LINE
- TPG line length == 1978 gives PIXEL_LONG_LINE
- TPG line length == 1976 gives Packet Payload CRC errors
This seems to indicate that the VI is set-up to accept 1948 + 28 pixel long lines by nvcamera-daemon, boldly ignoring the specified image geometry and boldly ignoring the previously printed “inW=1948” for VI.
How can that be? I’m stuck with exactly this problem for more than a week now. Could someone please explain what nvcamera-daemon is doing? I would even be willing to sign an NDA and look at the nvcamera-daemon (plus library) source code myself if you let me. No kidding!