diff options
-rw-r--r-- | src/libcamera/include/media_device.h | 10 | ||||
-rw-r--r-- | src/libcamera/media_device.cpp | 75 |
2 files changed, 53 insertions, 32 deletions
diff --git a/src/libcamera/include/media_device.h b/src/libcamera/include/media_device.h index bca7c9a1..74a67c81 100644 --- a/src/libcamera/include/media_device.h +++ b/src/libcamera/include/media_device.h @@ -28,6 +28,7 @@ public: void close(); int populate(); + bool valid() const { return valid_; } const std::string driver() const { return driver_; } const std::string devnode() const { return devnode_; } @@ -37,18 +38,19 @@ private: std::string driver_; std::string devnode_; int fd_; + bool valid_; std::map<unsigned int, MediaObject *> objects_; MediaObject *object(unsigned int id); - int addObject(MediaObject *obj); + bool addObject(MediaObject *obj); void clear(); std::vector<MediaEntity *> entities_; MediaEntity *getEntityByName(const std::string &name); - void populateEntities(const struct media_v2_topology &topology); - int populatePads(const struct media_v2_topology &topology); - int populateLinks(const struct media_v2_topology &topology); + bool populateEntities(const struct media_v2_topology &topology); + bool populatePads(const struct media_v2_topology &topology); + bool populateLinks(const struct media_v2_topology &topology); }; } /* namespace libcamera */ diff --git a/src/libcamera/media_device.cpp b/src/libcamera/media_device.cpp index d9a5196a..fd5a3174 100644 --- a/src/libcamera/media_device.cpp +++ b/src/libcamera/media_device.cpp @@ -56,7 +56,7 @@ namespace libcamera { * \param devnode The media device node path */ MediaDevice::MediaDevice(const std::string &devnode) - : devnode_(devnode), fd_(-1) + : devnode_(devnode), fd_(-1), valid_(false) { } @@ -99,6 +99,7 @@ void MediaDevice::clear() objects_.clear(); entities_.clear(); + valid_ = false; } /** @@ -163,18 +164,18 @@ void MediaDevice::close() * Add a new object to the global objects pool and fail if the object * has already been registered. */ -int MediaDevice::addObject(MediaObject *obj) +bool MediaDevice::addObject(MediaObject *obj) { if (objects_.find(obj->id()) != objects_.end()) { LOG(Error) << "Element with id " << obj->id() << " already enumerated."; - return -EEXIST; + return false; } objects_[obj->id()] = obj; - return 0; + return true; } /* @@ -201,7 +202,7 @@ MediaEntity *MediaDevice::getEntityByName(const std::string &name) return nullptr; } -int MediaDevice::populateLinks(const struct media_v2_topology &topology) +bool MediaDevice::populateLinks(const struct media_v2_topology &topology) { media_v2_link *mediaLinks = reinterpret_cast<media_v2_link *> (topology.ptr_links); @@ -222,7 +223,7 @@ int MediaDevice::populateLinks(const struct media_v2_topology &topology) if (!source) { LOG(Error) << "Failed to find pad with id: " << source_id; - return -ENODEV; + return false; } unsigned int sink_id = mediaLinks[i].sink_id; @@ -231,20 +232,23 @@ int MediaDevice::populateLinks(const struct media_v2_topology &topology) if (!sink) { LOG(Error) << "Failed to find pad with id: " << sink_id; - return -ENODEV; + return false; } MediaLink *link = new MediaLink(&mediaLinks[i], source, sink); + if (!addObject(link)) { + delete link; + return false; + } + source->addLink(link); sink->addLink(link); - - addObject(link); } - return 0; + return true; } -int MediaDevice::populatePads(const struct media_v2_topology &topology) +bool MediaDevice::populatePads(const struct media_v2_topology &topology) { media_v2_pad *mediaPads = reinterpret_cast<media_v2_pad *> (topology.ptr_pads); @@ -258,16 +262,19 @@ int MediaDevice::populatePads(const struct media_v2_topology &topology) if (!mediaEntity) { LOG(Error) << "Failed to find entity with id: " << entity_id; - return -ENODEV; + return false; } MediaPad *pad = new MediaPad(&mediaPads[i], mediaEntity); - mediaEntity->addPad(pad); + if (!addObject(pad)) { + delete pad; + return false; + } - addObject(pad); + mediaEntity->addPad(pad); } - return 0; + return true; } /* @@ -275,17 +282,22 @@ int MediaDevice::populatePads(const struct media_v2_topology &topology) * reference in the MediaObject global pool and in the global vector of * entities. */ -void MediaDevice::populateEntities(const struct media_v2_topology &topology) +bool MediaDevice::populateEntities(const struct media_v2_topology &topology) { media_v2_entity *mediaEntities = reinterpret_cast<media_v2_entity *> (topology.ptr_entities); for (unsigned int i = 0; i < topology.num_entities; ++i) { MediaEntity *entity = new MediaEntity(&mediaEntities[i]); + if (!addObject(entity)) { + delete entity; + return false; + } - addObject(entity); entities_.push_back(entity); } + + return true; } /** @@ -311,6 +323,8 @@ int MediaDevice::populate() __u64 version = -1; int ret; + clear(); + /* * Keep calling G_TOPOLOGY until the version number stays stable. */ @@ -343,25 +357,30 @@ int MediaDevice::populate() } /* Populate entities, pads and links. */ - populateEntities(topology); - - ret = populatePads(topology); - if (ret) - goto error_free_objs; - - ret = populateLinks(topology); -error_free_objs: - if (ret) - clear(); + if (populateEntities(topology) && + populatePads(topology) && + populateLinks(topology)) + valid_ = true; delete[] links; delete[] ents; delete[] pads; - return ret; + if (!valid_) { + clear(); + return -EINVAL; + } + + return 0; } /** + * \fn MediaDevice::valid() + * \brief Query whether the media graph is valid + * \return true if the media graph is valid, false otherwise + */ + +/** * \var MediaDevice::objects_ * \brief Global map of media objects (entities, pads, links) keyed by their * object id. |