diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libcamera/pipeline/simple/simple.cpp | 64 |
1 files changed, 60 insertions, 4 deletions
diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index 239f77ff..e8957b77 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -236,6 +236,8 @@ public: std::queue<std::map<unsigned int, FrameBuffer *>> converterQueue_; private: + static std::vector<const MediaPad *> routedSourcePads(MediaPad *sink); + void converterInputDone(FrameBuffer *buffer); void converterOutputDone(FrameBuffer *buffer); }; @@ -360,12 +362,29 @@ SimpleCameraData::SimpleCameraData(SimplePipelineHandler *pipe, break; } - /* The actual breadth-first search algorithm. */ visited.insert(entity); - for (MediaPad *pad : entity->pads()) { - if (!(pad->flags() & MEDIA_PAD_FL_SOURCE)) - continue; + /* + * Add direct downstream entities to the search queue. If the + * current entity supports the subdev internal routing API, + * restrict the search to downstream entities reachable through + * active routes. + */ + + std::vector<const MediaPad *> pads; + + if (sinkPad) + pads = routedSourcePads(sinkPad); + + if (pads.empty()) { + for (const MediaPad *pad : entity->pads()) { + if (!(pad->flags() & MEDIA_PAD_FL_SOURCE)) + continue; + pads.push_back(pad); + } + } + + for (const MediaPad *pad : pads) { for (MediaLink *link : pad->links()) { MediaEntity *next = link->sink()->entity(); if (visited.find(next) == visited.end()) { @@ -728,6 +747,43 @@ void SimpleCameraData::converterOutputDone(FrameBuffer *buffer) pipe->completeRequest(request); } +/* Retrieve all source pads connected to a sink pad through active routes. */ +std::vector<const MediaPad *> SimpleCameraData::routedSourcePads(MediaPad *sink) +{ + MediaEntity *entity = sink->entity(); + std::unique_ptr<V4L2Subdevice> subdev = + std::make_unique<V4L2Subdevice>(entity); + + int ret = subdev->open(); + if (ret < 0) + return {}; + + std::vector<struct v4l2_subdev_route> routes; + ret = subdev->getRouting(&routes); + if (ret < 0) + return {}; + + std::vector<const MediaPad *> pads; + + for (const struct v4l2_subdev_route &route : routes) { + if (sink->index() != route.sink_pad || + !(route.flags & V4L2_SUBDEV_ROUTE_FL_ACTIVE)) + continue; + + const MediaPad *pad = entity->getPadByIndex(route.source_pad); + if (!pad) { + LOG(SimplePipeline, Warning) + << "Entity " << entity->name() + << " has invalid route source pad " + << route.source_pad; + } + + pads.push_back(pad); + } + + return pads; +} + /* ----------------------------------------------------------------------------- * Camera Configuration */ |