4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Jetsonのカメラドライバを書く[モード追加とGStreamer編]

Last updated at Posted at 2023-06-04

はじめに

前の記事: Jetsonのカメラドライバを書く[Argus撮影編]
次の記事: Jetsonのカメラドライバを書く[デバッグ編]

前回、無事絵を取ることが出来ました。
しかしGStreamerで取得が出来ませんでした。
画像の大きさに問題があるようなので、モードを増やしてGStreamerで取得をしてみます。

モードの追加

イメージセンサは全画素撮影以外にも幾つかモードを持っているのが一般的です。
ドライバを見た感じ、IMX708は2x2binning、DOL HDR(Digital-Overlap High Dynamic Range)に対応してそうです。
特にbinningは画角を維持しながら高fpsで低ノイズ(平均化によって)に出来るので、高解像度を必要としないケースではとても助かります。

HDRはちょっと調べないと難しそうなのでまたの機会に。
今回は2x2binningの移植をします。

2x2Binningモード

移植するモードのRaspberryPiの実装です

imx708.c
{
    /* regular 2x2 binned. */
    .width = 2304,
    .height = 1296,
    .line_length_pix = 0x1e90,
    .crop = {
        .left = IMX708_PIXEL_ARRAY_LEFT,
        .top = IMX708_PIXEL_ARRAY_TOP,
        .width = 4608,
        .height = 2592,
    },
    .vblank_min = 40,
    .vblank_default = 1198,
    .reg_list = {
        .num_of_regs = ARRAY_SIZE(mode_2x2binned_regs),
        .regs = mode_2x2binned_regs,
    },
    .pixel_rate = 585600000,
    .exposure_lines_min = 4,
    .exposure_lines_step = 2,
    .hdr = false
},

こちらも前回のように計算すると以下のような設定となります。

item value
width 2304
height 1296
HSYNC(line_length) 7824
VSYNC 2494
pixel_rate(pix/s) 585600000
fps 30.01067593
hsync(us) 13.36065574
step exp(us) 26.72131148
min exp(us) 53.44262295
max exp(us) 32680.16393

コード追加作業

移植だけなので簡単ですね。

  • デバイスツリーにモードの追加
  • レジスタ設定の追加
  • 動作確認

device treeにモードを追加

hardware/nvidia/platform/t23x/p3768/kernel-dts/cvb/tegra234-p3768-0000-a0.dtsi
mode1 {
    mclk_khz = "24000";
    num_lanes = "2";
    tegra_sinterface = "serial_c";
    phy_mode = "DPHY";
    discontinuous_clk = "no";
    dpcm_enable = "false";
    cil_settletime = "0";
    lane_polarity = "0";

    active_w = "2304";
    active_h = "1296";
    mode_type = "bayer";
    pixel_phase = "rggb";
    csi_pixel_bit_depth = "10";
    readout_orientation = "0";
    line_length = "7824";
    inherent_gain = "1";
    pix_clk_hz = "300000000";

    gain_factor = "1";
    framerate_factor = "1000000";
    exposure_factor = "1000000"; /* us */
    min_gain_val = "112";
    max_gain_val = "960";
    step_gain_val = "1";
    default_gain = "112";
    min_hdr_ratio = "1";
    max_hdr_ratio = "1";
    min_framerate = "30010000";
    max_framerate = "30010000";
    step_framerate = "1";
    default_framerate = "30010000";
    min_exp_time = "52";
    max_exp_time = "32680";
    step_exp_time = "13";
    default_exp_time = "5000";

    embedded_metadata_height = "4";
};

レジスタ設定とモードリストの追加

レジスタ値は一箇所だけ変更します。VSYNC=2924のところですね。

static const imx708_reg imx708_mode_2304x1296_30fps[] = {
	{0x0342, 0x1E},
	{0x0343, 0x90},
-	{0x0340, 0x05},
-	{0x0341, 0x38},
+	{0x0340, 0x09},
+	{0x0341, 0xBE},
nvidia/drivers/media/i2c/imx708_mode_tbls.h
enum {
	IMX708_MODE_4608x2592_14FPS,
	IMX708_MODE_2304x1296_30FPS,

	IMX708_MODE_COMMON,
	IMX708_START_STREAM,
	IMX708_STOP_STREAM,
};

static const imx708_reg *mode_table[] = {
	[IMX708_MODE_4608x2592_14FPS] = imx708_mode_4608x2592_14fps,
	[IMX708_MODE_2304x1296_30FPS] = imx708_mode_2304x1296_30fps,

	[IMX708_MODE_COMMON] = imx708_mode_common,
	[IMX708_START_STREAM] = imx708_start,
	[IMX708_STOP_STREAM] = imx708_stop,
};

static const int imx708_14_fr[] = {
	14,
};

static const int imx708_30_fr[] = {
	30,
};

static const struct camera_common_frmfmt imx708_frmfmt[] = {
	{{4608, 2592}, imx708_14_fr, 1, 0, IMX708_MODE_4608x2592_14FPS},
	{{2304, 1296}, imx708_30_fr, 1, 0, IMX708_MODE_2304x1296_30FPS},
};

動作確認

gstreamerで撮影

gst-launch-1.0 nvarguscamerasrc sensor-id=0 sensor-mode=1 num-buffers=60 ! 'video/x-raw(memory:NVMM), width=1920, height=1080,format=NV12' ! nvvideoconvert ! x264enc ! h264parse ! qtmux ! filesink location=test.mp4

動画を貼れないので省略しますが、おそらくこのようなログが出てtest.mp4が作られたと思います。

Setting pipeline to PAUSED ...
Pipeline is live and does not need PREROLL ...
Setting pipeline to PLAYING ...
New clock: GstSystemClock
Redistribute latency...
GST_ARGUS: Creating output stream
CONSUMER: Waiting until producer is connected...
GST_ARGUS: Available Sensor modes :
GST_ARGUS: 4608 x 2592 FR = 14.350001 fps Duration = 69686408 ; Analog Gain range min 112.000000, max 960.000000; Exposure Range min 210000, max 68406000;

GST_ARGUS: 2304 x 1296 FR = 30.010000 fps Duration = 33322226 ; Analog Gain range min 112.000000, max 960.000000; Exposure Range min 52000, max 32680000;

GST_ARGUS: Running with following settings:
   Camera index = 1 
   Camera mode  = 1 
   Output Stream W = 2304 H = 1296 
   seconds to Run    = 0 
   Frame Rate = 30.010000 
GST_ARGUS: Setup Complete, Starting captures for 0 seconds
GST_ARGUS: Starting repeat capture requests.
CONSUMER: Producer has connected; continuing.
Got EOS from element "pipeline0".
Execution ended after 0:00:04.395651803
Setting pipeline to NULL ...
GST_ARGUS: Cleaning up
CONSUMER: Done Success
GST_ARGUS: Done Success
Freeing pipeline ...

フレームレートがわかるようにfpsdisplaysinkでみてみます。

gst-launch-1.0 nvarguscamerasrc sensor-id=1 sensor-mode=1 ! nvvideoconvert ! fpsdisplaysink

image.png

無事30fpsで撮影できました :tada:
写っているのはカーテンです。室内灯だけなので200lxもないはずですが、結構見えてますね。

Cropモード

単純移植は簡単でちょっと物足りないですね。
もう一つCropされたモードがあるのでレジスタの意味を推測しながら追加してみます。

モードの追加

566400000/(5216*904) = 120.1205となるので、これで120fps出るはずです。

item value
width 1536
height 864
HSYNC(line_length) 0x1460=5216
VSYNC 904
pixel_rate(pix/s) 566400000
fps 120.1205
hsync(us) 6.168
step exp(us) 24.672
min exp(us) 49.344
max exp(us) 4120.224

Cropモードのレジスタ設定

2x2binningモードも画素読み出し自体は全画素が対象でした。
今度はCropするためActiveAreaを明示的に指定します。
既存のレジスタ設定の違いを読むと、おそらくレジスタの意味は次のようになっていると思われます。
データレートの設定がありそうですがこちらはわからず。
しかし大きくサイズが変わらない限り欲しい形状の画像を得ることはできそうです。

static const imx708_reg imx708_mode_1536x864_120fps[] = {
	/* HSYNC 5216 */
	{0x0342, 0x14},
	{0x0343, 0x60},
	/* VSYNC 904 */
	{0x0340, 0x03},
	{0x0341, 0x60},
	/* active area left */
	{0x0344, 0x03},
	{0x0345, 0x00},
	/* active area top */
	{0x0346, 0x01},
	{0x0347, 0xB0},
	/* active area right */
	{0x0348, 0x0E},
	{0x0349, 0xFF},
	/* active area bottom */
	{0x034A, 0x08},
	{0x034B, 0x6F},

	/* width 1536 */
	{0x040C, 0x06},
	{0x040D, 0x00},
	/* height 864 */
	{0x040E, 0x03},
	{0x040F, 0x60},
	/* width 1536 */
	{0x034C, 0x06},
	{0x034D, 0x00},
	/* height 864 */
	{0x034E, 0x03},
	{0x034F, 0x60},

GStreamerで撮影、記録、配信

いつものようにビルドして転送します。
フレームレートがわかるようにfpsdisplaysinkで撮影

gst-launch-1.0 nvarguscamerasrc sensor-id=1 sensor-mode=1 ! nvvideoconvert ! fpsdisplaysink

image.png

期待通り120fpsを超えました :tada:
画角も少し狭くなっているのがわかりますね。

まとめ

今回はモードの追加をしてGStreamerで記録、プレビューをしました。
GStreamerで読み出せれば加工や配信、アプリケーションとの連携など比較的容易に実現できます。

またモードを比較することでどのレジスタを変更したら、限られたモードしかないUVCカメラと比較して欲しい撮影モードを自分で作れるのが良いですね。

ほとんど単なる移植なのでうまく行きました。
次回、うまく行かない時に使える調査方法の話をします。

この記事時点のソースコードはGitHubで公開しています。

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?