summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorUmang Jain <umang.jain@ideasonboard.com>2022-04-08 14:05:08 +0530
committerUmang Jain <umang.jain@ideasonboard.com>2022-04-08 14:05:11 +0530
commitd630cc06db1f8e460ec85ac2b398880a56d94aaf (patch)
tree1d1a0dd8637f82f9a3529d6c0b954d37aa00e992 /src
parent9230cf69cb0907548eb8cc7460547db053615192 (diff)
ipa: ipu3: Inline parseStatistics() into processStatsBuffer()
Since we have moved away from switch/case on the operation ID, there's little reason to split the operation in two functions. Signed-off-by: Umang Jain <umang.jain@ideasonboard.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
Diffstat (limited to 'src')
-rw-r--r--src/ipa/ipu3/ipu3.cpp54
1 files changed, 19 insertions, 35 deletions
diff --git a/src/ipa/ipu3/ipu3.cpp b/src/ipa/ipu3/ipu3.cpp
index d77d6686..dd6cfd79 100644
--- a/src/ipa/ipu3/ipu3.cpp
+++ b/src/ipa/ipu3/ipu3.cpp
@@ -156,9 +156,6 @@ private:
ControlInfoMap *ipaControls);
void updateSessionConfiguration(const ControlInfoMap &sensorControls);
- void parseStatistics(unsigned int frame,
- int64_t frameTimestamp,
- const ipu3_uapi_stats_3a *stats);
bool validateSensorControls();
void setControls(unsigned int frame);
@@ -546,11 +543,15 @@ void IPAIPU3::fillParamsBuffer(const uint32_t frame, const uint32_t bufferId)
}
/**
- * \brief Process statistics after ISP completion
+ * \brief Process the statistics generated by the ImgU
* \param[in] frame The frame number
* \param[in] frameTimestamp Timestamp of the frame
* \param[in] bufferId ID of the statistics buffer
* \param[in] sensorControls Sensor controls
+ *
+ * Parse the most recently processed image statistics from the ImgU. The
+ * statistics are passed to each algorithm module to run their calculations and
+ * update their state accordingly.
*/
void IPAIPU3::processStatsBuffer(const uint32_t frame,
[[maybe_unused]] const int64_t frameTimestamp,
@@ -569,37 +570,6 @@ void IPAIPU3::processStatsBuffer(const uint32_t frame,
context_.frameContext.sensor.exposure = sensorControls.get(V4L2_CID_EXPOSURE).get<int32_t>();
context_.frameContext.sensor.gain = camHelper_->gain(sensorControls.get(V4L2_CID_ANALOGUE_GAIN).get<int32_t>());
- parseStatistics(frame, frameTimestamp, stats);
-}
-
-/**
- * \brief Queue a request and process the control list from the application
- * \param[in] frame The number of the frame which will be processed next
- * \param[in] controls The controls for the \a frame
- *
- * Parse the request to handle any IPA-managed controls that were set from the
- * application such as manual sensor settings.
- */
-void IPAIPU3::queueRequest([[maybe_unused]] const uint32_t frame,
- [[maybe_unused]] const ControlList &controls)
-{
- /* \todo Start processing for 'frame' based on 'controls'. */
-}
-
-/**
- * \brief Process the statistics generated by the ImgU
- * \param[in] frame The number of the latest frame processed
- * \param[in] frameTimestamp The current frame timestamp
- * \param[in] stats The IPU3 statistics and ISP results
- *
- * Parse the most recently processed image statistics from the ImgU. The
- * statistics are passed to each algorithm module to run their calculations and
- * update their state accordingly.
- */
-void IPAIPU3::parseStatistics(unsigned int frame,
- [[maybe_unused]] int64_t frameTimestamp,
- const ipu3_uapi_stats_3a *stats)
-{
double lineDuration = context_.configuration.sensor.lineDuration.get<std::micro>();
int32_t vBlank = context_.configuration.sensor.defVBlank;
ControlList ctrls(controls::controls);
@@ -631,6 +601,20 @@ void IPAIPU3::parseStatistics(unsigned int frame,
}
/**
+ * \brief Queue a request and process the control list from the application
+ * \param[in] frame The number of the frame which will be processed next
+ * \param[in] controls The controls for the \a frame
+ *
+ * Parse the request to handle any IPA-managed controls that were set from the
+ * application such as manual sensor settings.
+ */
+void IPAIPU3::queueRequest([[maybe_unused]] const uint32_t frame,
+ [[maybe_unused]] const ControlList &controls)
+{
+ /* \todo Start processing for 'frame' based on 'controls'. */
+}
+
+/**
* \brief Handle sensor controls for a given \a frame number
* \param[in] frame The frame on which the sensor controls should be set
*
-utils.c - GStreamer libcamera Utility Function */ #include "gstlibcamera-utils.h" #include <libcamera/formats.h> using namespace libcamera; static struct { GstVideoFormat gst_format; PixelFormat format; } format_map[] = { /* Compressed */ { GST_VIDEO_FORMAT_ENCODED, formats::MJPEG }, /* RGB */ { GST_VIDEO_FORMAT_RGB, formats::BGR888 }, { GST_VIDEO_FORMAT_BGR, formats::RGB888 }, { GST_VIDEO_FORMAT_ARGB, formats::BGRA8888 }, /* YUV Semiplanar */ { GST_VIDEO_FORMAT_NV12, formats::NV12 }, { GST_VIDEO_FORMAT_NV21, formats::NV21 }, { GST_VIDEO_FORMAT_NV16, formats::NV16 }, { GST_VIDEO_FORMAT_NV61, formats::NV61 }, { GST_VIDEO_FORMAT_NV24, formats::NV24 }, /* YUV Planar */ { GST_VIDEO_FORMAT_I420, formats::YUV420 }, { GST_VIDEO_FORMAT_YV12, formats::YVU420 }, { GST_VIDEO_FORMAT_Y42B, formats::YUV422 }, /* YUV Packed */ { GST_VIDEO_FORMAT_UYVY, formats::UYVY }, { GST_VIDEO_FORMAT_VYUY, formats::VYUY }, { GST_VIDEO_FORMAT_YUY2, formats::YUYV }, { GST_VIDEO_FORMAT_YVYU, formats::YVYU }, /* \todo NV42 is used in libcamera but is not mapped in GStreamer yet. */ }; static GstVideoFormat pixel_format_to_gst_format(const PixelFormat &format) { for (const auto &item : format_map) { if (item.format == format) return item.gst_format; } return GST_VIDEO_FORMAT_UNKNOWN; } static PixelFormat gst_format_to_pixel_format(GstVideoFormat gst_format) { if (gst_format == GST_VIDEO_FORMAT_ENCODED) return PixelFormat{}; for (const auto &item : format_map) if (item.gst_format == gst_format) return item.format; return PixelFormat{}; } static GstStructure * bare_structure_from_format(const PixelFormat &format) { GstVideoFormat gst_format = pixel_format_to_gst_format(format); if (gst_format == GST_VIDEO_FORMAT_UNKNOWN) return nullptr; if (gst_format != GST_VIDEO_FORMAT_ENCODED) return gst_structure_new("video/x-raw", "format", G_TYPE_STRING, gst_video_format_to_string(gst_format), nullptr); switch (format) { case formats::MJPEG: return gst_structure_new_empty("image/jpeg"); default: return nullptr; } } GstCaps * gst_libcamera_stream_formats_to_caps(const StreamFormats &formats) { GstCaps *caps = gst_caps_new_empty(); for (PixelFormat pixelformat : formats.pixelformats()) { g_autoptr(GstStructure) bare_s = bare_structure_from_format(pixelformat); if (!bare_s) { GST_WARNING("Unsupported DRM format %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS(pixelformat)); continue; } for (const Size &size : formats.sizes(pixelformat)) { GstStructure *s = gst_structure_copy(bare_s); gst_structure_set(s, "width", G_TYPE_INT, size.width, "height", G_TYPE_INT, size.height, nullptr); gst_caps_append_structure(caps, s); } const SizeRange &range = formats.range(pixelformat); if (range.hStep && range.vStep) { GstStructure *s = gst_structure_copy(bare_s); GValue val = G_VALUE_INIT; g_value_init(&val, GST_TYPE_INT_RANGE); gst_value_set_int_range_step(&val, range.min.width, range.max.width, range.hStep); gst_structure_set_value(s, "width", &val); gst_value_set_int_range_step(&val, range.min.height, range.max.height, range.vStep); gst_structure_set_value(s, "height", &val); g_value_unset(&val); gst_caps_append_structure(caps, s); } } return caps; } GstCaps * gst_libcamera_stream_configuration_to_caps(const StreamConfiguration &stream_cfg) { GstCaps *caps = gst_caps_new_empty(); GstStructure *s = bare_structure_from_format(stream_cfg.pixelFormat); gst_structure_set(s, "width", G_TYPE_INT, stream_cfg.size.width, "height", G_TYPE_INT, stream_cfg.size.height, nullptr); gst_caps_append_structure(caps, s); return caps; } void gst_libcamera_configure_stream_from_caps(StreamConfiguration &stream_cfg, GstCaps *caps) { GstVideoFormat gst_format = pixel_format_to_gst_format(stream_cfg.pixelFormat); guint i; gint best_fixed = -1, best_in_range = -1; GstStructure *s; /* * These are delta weight computed from: * ABS(width - stream_cfg.size.width) * ABS(height - stream_cfg.size.height) */ guint best_fixed_delta = G_MAXUINT; guint best_in_range_delta = G_MAXUINT; /* First fixate the caps using default configuration value. */ g_assert(gst_caps_is_writable(caps)); /* Lookup the structure for a close match to the stream_cfg.size */ for (i = 0; i < gst_caps_get_size(caps); i++) { s = gst_caps_get_structure(caps, i); gint width, height; guint delta; if (gst_structure_has_field_typed(s, "width", G_TYPE_INT) && gst_structure_has_field_typed(s, "height", G_TYPE_INT)) { gst_structure_get_int(s, "width", &width); gst_structure_get_int(s, "height", &height); delta = ABS(width - (gint)stream_cfg.size.width) * ABS(height - (gint)stream_cfg.size.height); if (delta < best_fixed_delta) { best_fixed_delta = delta; best_fixed = i; } } else { gst_structure_fixate_field_nearest_int(s, "width", stream_cfg.size.width); gst_structure_fixate_field_nearest_int(s, "height", stream_cfg.size.height); gst_structure_get_int(s, "width", &width); gst_structure_get_int(s, "height", &height); delta = ABS(width - (gint)stream_cfg.size.width) * ABS(height - (gint)stream_cfg.size.height); if (delta < best_in_range_delta) { best_in_range_delta = delta; best_in_range = i; } } } /* Prefer reliable fixed value over ranges */ if (best_fixed >= 0) s = gst_caps_get_structure(caps, best_fixed); else s = gst_caps_get_structure(caps, best_in_range); if (gst_structure_has_name(s, "video/x-raw")) { const gchar *format = gst_video_format_to_string(gst_format); gst_structure_fixate_field_string(s, "format", format); } /* Then configure the stream with the result. */ if (gst_structure_has_name(s, "video/x-raw")) { const gchar *format = gst_structure_get_string(s, "format"); gst_format = gst_video_format_from_string(format); stream_cfg.pixelFormat = gst_format_to_pixel_format(gst_format); } else if (gst_structure_has_name(s, "image/jpeg")) { stream_cfg.pixelFormat = formats::MJPEG; } else { g_critical("Unsupported media type: %s", gst_structure_get_name(s)); } gint width, height; gst_structure_get_int(s, "width", &width); gst_structure_get_int(s, "height", &height); stream_cfg.size.width = width; stream_cfg.size.height = height; } void gst_libcamera_resume_task(GstTask *task) { /* We only want to resume the task if it's paused. */ GLibLocker lock(GST_OBJECT(task)); if (GST_TASK_STATE(task) == GST_TASK_PAUSED) { GST_TASK_STATE(task) = GST_TASK_STARTED; GST_TASK_SIGNAL(task); } } G_LOCK_DEFINE_STATIC(cm_singleton_lock); static std::weak_ptr<CameraManager> cm_singleton_ptr; std::shared_ptr<CameraManager>