Add imx296 libargus camera process

This takes NVIDIA's example code and adapts it to read our imx296
images, reorder the bytes to fit into our flatbuffers, and send them.

It still needs a bit of RT tuning, but it works!

Change-Id: Ie1b516ee4ba1536cef18495c305759a21e72add9
Signed-off-by: Austin Schuh <austin.linux@gmail.com>
diff --git a/frc971/orin/crcv_generator.cc b/frc971/orin/crcv_generator.cc
index 99318e6..5c72385 100644
--- a/frc971/orin/crcv_generator.cc
+++ b/frc971/orin/crcv_generator.cc
@@ -20,17 +20,17 @@
 namespace {
 
 template <typename T>
-void SetRowMajor(T *buffer_parameter, int cols, int rows) {
-  buffer_parameter->dim(0).set_stride(3);
+void SetRowMajor(T *buffer_parameter, int cols, int rows, int channels) {
+  buffer_parameter->dim(0).set_stride(channels);
   buffer_parameter->dim(0).set_extent(cols);
   buffer_parameter->dim(0).set_min(0);
 
-  buffer_parameter->dim(1).set_stride(cols * 3);
+  buffer_parameter->dim(1).set_stride(cols * channels);
   buffer_parameter->dim(1).set_extent(rows);
   buffer_parameter->dim(1).set_min(0);
 
   buffer_parameter->dim(2).set_stride(1);
-  buffer_parameter->dim(2).set_extent(3);
+  buffer_parameter->dim(2).set_extent(channels);
   buffer_parameter->dim(2).set_min(0);
 }
 }  // namespace
@@ -86,7 +86,59 @@
     output.vectorize(col, 8);
     output.unroll(col, 4);
 
-    SetRowMajor(&output, cols, rows);
+    SetRowMajor(&output, cols, rows, 3);
+  }
+};
+
+class YCbCr422 : public Halide::Generator<YCbCr422> {
+ public:
+  GeneratorParam<int> cols{"cols", 0};
+  GeneratorParam<int> rows{"rows", 0};
+  GeneratorParam<int> ystride{"ystride", 0};
+  GeneratorParam<int> cbcrstride{"cbcrstride", 0};
+
+  Input<Buffer<uint8_t, 2>> input_y{"y"};
+  Input<Buffer<uint8_t, 3>> input_cbcr{"cbcr"};
+  Output<Buffer<uint8_t, 3>> output{"output"};
+
+  Var col{"col"}, row{"row"}, channel{"channel"};
+
+  // Everything is indexed as col, row, channel.
+  void generate() {
+    CHECK(cols > 0, "Must specify a cols");
+    CHECK((cols % 2) == 0, "Must specify a cols with an even number of cols");
+    CHECK(rows > 0, "Must specify a rows");
+
+    input_y.dim(0).set_stride(1);
+    input_y.dim(0).set_extent(cols);
+    input_y.dim(0).set_min(0);
+
+    input_y.dim(1).set_stride(ystride);
+    input_y.dim(1).set_extent(rows);
+    input_y.dim(1).set_min(0);
+
+    input_cbcr.dim(0).set_stride(2);
+    input_cbcr.dim(0).set_extent(cols / 2);
+    input_cbcr.dim(0).set_min(0);
+
+    input_cbcr.dim(1).set_stride(cbcrstride);
+    input_cbcr.dim(1).set_extent(rows);
+    input_cbcr.dim(1).set_min(0);
+
+    input_cbcr.dim(2).set_stride(1);
+    input_cbcr.dim(2).set_extent(2);
+    input_cbcr.dim(2).set_min(0);
+
+    output(col, row, channel) = Halide::select(
+        channel == 0, input_y(col, row), input_cbcr(col / 2, row, col % 2));
+
+    output.reorder(channel, col, row);
+    output.unroll(channel);
+
+    output.vectorize(col, 8);
+    output.unroll(col, 4);
+
+    SetRowMajor(&output, cols, rows, 2);
   }
 };
 
@@ -94,3 +146,4 @@
 }  // namespace frc971
 
 HALIDE_REGISTER_GENERATOR(frc971::orin::YCbCr, ycbcr)
+HALIDE_REGISTER_GENERATOR(frc971::orin::YCbCr422, ycbcr422)