summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/libcamera/internal/v4l2_subdevice.h19
-rw-r--r--src/libcamera/pipeline/imx8-isi/imx8-isi.cpp14
-rw-r--r--src/libcamera/pipeline/simple/simple.cpp8
-rw-r--r--src/libcamera/v4l2_subdevice.cpp108
4 files changed, 123 insertions, 26 deletions
diff --git a/include/libcamera/internal/v4l2_subdevice.h b/include/libcamera/internal/v4l2_subdevice.h
index 2939dc24..01ed4c2f 100644
--- a/include/libcamera/internal/v4l2_subdevice.h
+++ b/include/libcamera/internal/v4l2_subdevice.h
@@ -95,7 +95,23 @@ public:
unsigned int stream;
};
- using Routing = std::vector<struct v4l2_subdev_route>;
+ struct Route {
+ Route()
+ : flags(0)
+ {
+ }
+
+ Route(const Stream &snk, const Stream &src, uint32_t f)
+ : sink(snk), source(src), flags(f)
+ {
+ }
+
+ Stream sink;
+ Stream source;
+ uint32_t flags;
+ };
+
+ using Routing = std::vector<Route>;
explicit V4L2Subdevice(const MediaEntity *entity);
~V4L2Subdevice();
@@ -174,6 +190,7 @@ static inline bool operator!=(const V4L2Subdevice::Stream &lhs,
}
std::ostream &operator<<(std::ostream &out, const V4L2Subdevice::Stream &stream);
+std::ostream &operator<<(std::ostream &out, const V4L2Subdevice::Route &route);
std::ostream &operator<<(std::ostream &out, const V4L2Subdevice::Routing &routing);
} /* namespace libcamera */
diff --git a/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp b/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp
index a3782aea..63082cea 100644
--- a/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp
+++ b/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp
@@ -827,16 +827,10 @@ int PipelineHandlerISI::configure(Camera *camera, CameraConfiguration *c)
unsigned int xbarFirstSource = crossbar_->entity()->pads().size() / 2 + 1;
for (const auto &[idx, config] : utils::enumerate(*c)) {
- struct v4l2_subdev_route route = {
- .sink_pad = data->xbarSink_,
- .sink_stream = 0,
- .source_pad = static_cast<uint32_t>(xbarFirstSource + idx),
- .source_stream = 0,
- .flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE,
- .reserved = {}
- };
-
- routing.push_back(route);
+ uint32_t sourcePad = xbarFirstSource + idx;
+ routing.emplace_back(V4L2Subdevice::Stream{ data->xbarSink_, 0 },
+ V4L2Subdevice::Stream{ sourcePad, 0 },
+ V4L2_SUBDEV_ROUTE_FL_ACTIVE);
}
int ret = crossbar_->setRouting(&routing, V4L2Subdevice::ActiveFormat);
diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp
index feea26fd..01f2a977 100644
--- a/src/libcamera/pipeline/simple/simple.cpp
+++ b/src/libcamera/pipeline/simple/simple.cpp
@@ -852,17 +852,17 @@ std::vector<const MediaPad *> SimpleCameraData::routedSourcePads(MediaPad *sink)
std::vector<const MediaPad *> pads;
- for (const struct v4l2_subdev_route &route : routing) {
- if (sink->index() != route.sink_pad ||
+ for (const V4L2Subdevice::Route &route : routing) {
+ if (sink->index() != route.sink.pad ||
!(route.flags & V4L2_SUBDEV_ROUTE_FL_ACTIVE))
continue;
- const MediaPad *pad = entity->getPadByIndex(route.source_pad);
+ const MediaPad *pad = entity->getPadByIndex(route.source.pad);
if (!pad) {
LOG(SimplePipeline, Warning)
<< "Entity " << entity->name()
<< " has invalid route source pad "
- << route.source_pad;
+ << route.source.pad;
}
pads.push_back(pad);
diff --git a/src/libcamera/v4l2_subdevice.cpp b/src/libcamera/v4l2_subdevice.cpp
index deef681e..1076b700 100644
--- a/src/libcamera/v4l2_subdevice.cpp
+++ b/src/libcamera/v4l2_subdevice.cpp
@@ -899,6 +899,53 @@ std::ostream &operator<<(std::ostream &out, const V4L2Subdevice::Stream &stream)
}
/**
+ * \class V4L2Subdevice::Route
+ * \brief V4L2 subdevice routing table entry
+ *
+ * This class models a route in the subdevice routing table. It is similar to
+ * the v4l2_subdev_route structure, but uses the V4L2Subdevice::Stream class
+ * for easier usage with the V4L2Subdevice stream-aware functions.
+ *
+ * \var V4L2Subdevice::Route::sink
+ * \brief The sink stream of the route
+ *
+ * \var V4L2Subdevice::Route::source
+ * \brief The source stream of the route
+ *
+ * \var V4L2Subdevice::Route::flags
+ * \brief The route flags (V4L2_SUBDEV_ROUTE_FL_*)
+ */
+
+/**
+ * \fn V4L2Subdevice::Route::Route()
+ * \brief Construct a Route with default streams
+ */
+
+/**
+ * \fn V4L2Subdevice::Route::Route(const Stream &sink, const Stream &source,
+ * uint32_t flags)
+ * \brief Construct a Route from \a sink to \a source
+ * \param[in] sink The sink stream
+ * \param[in] source The source stream
+ * \param[in] flags The route flags
+ */
+
+/**
+ * \brief Insert a text representation of a V4L2Subdevice::Route into an
+ * output stream
+ * \param[in] out The output stream
+ * \param[in] route The V4L2Subdevice::Route
+ * \return The output stream \a out
+ */
+std::ostream &operator<<(std::ostream &out, const V4L2Subdevice::Route &route)
+{
+ out << route.sink << " -> " << route.source
+ << " (" << utils::hex(route.flags) << ")";
+
+ return out;
+}
+
+/**
* \typedef V4L2Subdevice::Routing
* \brief V4L2 subdevice routing table
*
@@ -907,7 +954,7 @@ std::ostream &operator<<(std::ostream &out, const V4L2Subdevice::Stream &stream)
/**
* \brief Insert a text representation of a V4L2Subdevice::Routing into an
- * output stream
+ * output stream
* \param[in] out The output stream
* \param[in] routing The V4L2Subdevice::Routing
* \return The output stream \a out
@@ -915,10 +962,7 @@ std::ostream &operator<<(std::ostream &out, const V4L2Subdevice::Stream &stream)
std::ostream &operator<<(std::ostream &out, const V4L2Subdevice::Routing &routing)
{
for (const auto &[i, route] : utils::enumerate(routing)) {
- out << "[" << i << "] "
- << route.sink_pad << "/" << route.sink_stream << " -> "
- << route.source_pad << "/" << route.source_stream
- << " (" << utils::hex(route.flags) << ")";
+ out << "[" << i << "] " << route;
if (i != routing.size() - 1)
out << ", ";
}
@@ -1272,6 +1316,30 @@ int V4L2Subdevice::setFormat(const Stream &stream, V4L2SubdeviceFormat *format,
* \return 0 on success or a negative error code otherwise
*/
+namespace {
+
+void routeFromKernel(V4L2Subdevice::Route &route,
+ const struct v4l2_subdev_route &kroute)
+{
+ route.sink.pad = kroute.sink_pad;
+ route.sink.stream = kroute.sink_stream;
+ route.source.pad = kroute.source_pad;
+ route.source.stream = kroute.source_stream;
+ route.flags = kroute.flags;
+}
+
+void routeToKernel(const V4L2Subdevice::Route &route,
+ struct v4l2_subdev_route &kroute)
+{
+ kroute.sink_pad = route.sink.pad;
+ kroute.sink_stream = route.sink.stream;
+ kroute.source_pad = route.source.pad;
+ kroute.source_stream = route.source.stream;
+ kroute.flags = route.flags;
+}
+
+} /* namespace */
+
/**
* \brief Retrieve the subdevice's internal routing table
* \param[out] routing The routing table
@@ -1282,6 +1350,8 @@ int V4L2Subdevice::setFormat(const Stream &stream, V4L2SubdeviceFormat *format,
*/
int V4L2Subdevice::getRouting(Routing *routing, Whence whence)
{
+ routing->clear();
+
if (!caps_.hasStreams())
return 0;
@@ -1300,8 +1370,8 @@ int V4L2Subdevice::getRouting(Routing *routing, Whence whence)
return ret;
}
- routing->resize(rt.num_routes);
- rt.routes = reinterpret_cast<uintptr_t>(routing->data());
+ std::vector<struct v4l2_subdev_route> routes{ rt.num_routes };
+ rt.routes = reinterpret_cast<uintptr_t>(routes.data());
ret = ioctl(VIDIOC_SUBDEV_G_ROUTING, &rt);
if (ret) {
@@ -1310,11 +1380,16 @@ int V4L2Subdevice::getRouting(Routing *routing, Whence whence)
return ret;
}
- if (rt.num_routes != routing->size()) {
+ if (rt.num_routes != routes.size()) {
LOG(V4L2, Error) << "Invalid number of routes";
return -EINVAL;
}
+ routing->resize(rt.num_routes);
+
+ for (const auto &[i, route] : utils::enumerate(routes))
+ routeFromKernel((*routing)[i], route);
+
return 0;
}
@@ -1332,13 +1407,20 @@ int V4L2Subdevice::getRouting(Routing *routing, Whence whence)
*/
int V4L2Subdevice::setRouting(Routing *routing, Whence whence)
{
- if (!caps_.hasStreams())
+ if (!caps_.hasStreams()) {
+ routing->clear();
return 0;
+ }
+
+ std::vector<struct v4l2_subdev_route> routes{ routing->size() };
+
+ for (const auto &[i, route] : utils::enumerate(*routing))
+ routeToKernel(route, routes[i]);
struct v4l2_subdev_routing rt = {};
rt.which = whence;
- rt.num_routes = routing->size();
- rt.routes = reinterpret_cast<uintptr_t>(routing->data());
+ rt.num_routes = routes.size();
+ rt.routes = reinterpret_cast<uintptr_t>(routes.data());
int ret = ioctl(VIDIOC_SUBDEV_S_ROUTING, &rt);
if (ret) {
@@ -1346,8 +1428,12 @@ int V4L2Subdevice::setRouting(Routing *routing, Whence whence)
return ret;
}
+ routes.resize(rt.num_routes);
routing->resize(rt.num_routes);
+ for (const auto &[i, route] : utils::enumerate(routes))
+ routeFromKernel((*routing)[i], route);
+
return 0;
}