diff --git a/include/ipa/ipa_interface.h b/include/ipa/ipa_interface.h index 229d1124b..e65844bc7 100644 --- a/include/ipa/ipa_interface.h +++ b/include/ipa/ipa_interface.h @@ -64,6 +64,8 @@ struct ipa_context_ops { void (*destroy)(struct ipa_context *ctx); void *(*get_interface)(struct ipa_context *ctx); void (*init)(struct ipa_context *ctx); + int (*start)(struct ipa_context *ctx); + void (*stop)(struct ipa_context *ctx); void (*register_callbacks)(struct ipa_context *ctx, const struct ipa_callback_ops *callbacks, void *cb_ctx); @@ -120,6 +122,8 @@ public: virtual ~IPAInterface() {} virtual int init() = 0; + virtual int start() = 0; + virtual void stop() = 0; virtual void configure(const std::map &streamConfig, const std::map &entityControls) = 0; diff --git a/include/ipa/ipa_vimc.h b/include/ipa/ipa_vimc.h index 9add122cf..8e82dd94b 100644 --- a/include/ipa/ipa_vimc.h +++ b/include/ipa/ipa_vimc.h @@ -15,6 +15,8 @@ namespace libcamera { enum IPAOperationCode { IPAOperationNone, IPAOperationInit, + IPAOperationStart, + IPAOperationStop, }; } /* namespace libcamera */ diff --git a/src/ipa/libipa/ipa_interface_wrapper.cpp b/src/ipa/libipa/ipa_interface_wrapper.cpp index b93c1c1f1..f50f93a01 100644 --- a/src/ipa/libipa/ipa_interface_wrapper.cpp +++ b/src/ipa/libipa/ipa_interface_wrapper.cpp @@ -86,6 +86,20 @@ void IPAInterfaceWrapper::init(struct ipa_context *_ctx) ctx->ipa_->init(); } +int IPAInterfaceWrapper::start(struct ipa_context *_ctx) +{ + IPAInterfaceWrapper *ctx = static_cast(_ctx); + + return ctx->ipa_->start(); +} + +void IPAInterfaceWrapper::stop(struct ipa_context *_ctx) +{ + IPAInterfaceWrapper *ctx = static_cast(_ctx); + + ctx->ipa_->stop(); +} + void IPAInterfaceWrapper::register_callbacks(struct ipa_context *_ctx, const struct ipa_callback_ops *callbacks, void *cb_ctx) @@ -234,6 +248,8 @@ const struct ipa_context_ops IPAInterfaceWrapper::operations_ = { .destroy = &IPAInterfaceWrapper::destroy, .get_interface = &IPAInterfaceWrapper::get_interface, .init = &IPAInterfaceWrapper::init, + .start = &IPAInterfaceWrapper::start, + .stop = &IPAInterfaceWrapper::stop, .register_callbacks = &IPAInterfaceWrapper::register_callbacks, .configure = &IPAInterfaceWrapper::configure, .map_buffers = &IPAInterfaceWrapper::map_buffers, diff --git a/src/ipa/libipa/ipa_interface_wrapper.h b/src/ipa/libipa/ipa_interface_wrapper.h index 3fb7b4476..e4bc6dd45 100644 --- a/src/ipa/libipa/ipa_interface_wrapper.h +++ b/src/ipa/libipa/ipa_interface_wrapper.h @@ -24,6 +24,8 @@ private: static void destroy(struct ipa_context *ctx); static void *get_interface(struct ipa_context *ctx); static void init(struct ipa_context *ctx); + static int start(struct ipa_context *ctx); + static void stop(struct ipa_context *ctx); static void register_callbacks(struct ipa_context *ctx, const struct ipa_callback_ops *callbacks, void *cb_ctx); diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp index 438b3c66f..af38e3299 100644 --- a/src/ipa/rkisp1/rkisp1.cpp +++ b/src/ipa/rkisp1/rkisp1.cpp @@ -33,6 +33,8 @@ class IPARkISP1 : public IPAInterface { public: int init() override { return 0; } + int start() override { return 0; } + void stop() override {} void configure(const std::map &streamConfig, const std::map &entityControls) override; diff --git a/src/ipa/vimc/vimc.cpp b/src/ipa/vimc/vimc.cpp index 6e2095b56..566a66e40 100644 --- a/src/ipa/vimc/vimc.cpp +++ b/src/ipa/vimc/vimc.cpp @@ -32,6 +32,10 @@ public: ~IPAVimc(); int init() override; + + int start() override; + void stop() override; + void configure(const std::map &streamConfig, const std::map &entityControls) override {} void mapBuffers(const std::vector &buffers) override {} @@ -66,6 +70,22 @@ int IPAVimc::init() return 0; } +int IPAVimc::start() +{ + trace(IPAOperationStart); + + LOG(IPAVimc, Debug) << "start vimc IPA!"; + + return 0; +} + +void IPAVimc::stop() +{ + trace(IPAOperationStop); + + LOG(IPAVimc, Debug) << "stop vimc IPA!"; +} + void IPAVimc::initTrace() { struct stat fifoStat; diff --git a/src/libcamera/include/ipa_context_wrapper.h b/src/libcamera/include/ipa_context_wrapper.h index c9e194120..0a48bfe73 100644 --- a/src/libcamera/include/ipa_context_wrapper.h +++ b/src/libcamera/include/ipa_context_wrapper.h @@ -20,6 +20,8 @@ public: ~IPAContextWrapper(); int init() override; + int start() override; + void stop() override; void configure(const std::map &streamConfig, const std::map &entityControls) override; diff --git a/src/libcamera/ipa_context_wrapper.cpp b/src/libcamera/ipa_context_wrapper.cpp index 946a2fd8c..ab6ce396b 100644 --- a/src/libcamera/ipa_context_wrapper.cpp +++ b/src/libcamera/ipa_context_wrapper.cpp @@ -82,6 +82,28 @@ int IPAContextWrapper::init() return 0; } +int IPAContextWrapper::start() +{ + if (intf_) + return intf_->start(); + + if (!ctx_) + return 0; + + return ctx_->ops->start(ctx_); +} + +void IPAContextWrapper::stop() +{ + if (intf_) + return intf_->stop(); + + if (!ctx_) + return; + + ctx_->ops->stop(ctx_); +} + void IPAContextWrapper::configure(const std::map &streamConfig, const std::map &entityControls) { diff --git a/src/libcamera/ipa_interface.cpp b/src/libcamera/ipa_interface.cpp index 5959e7ded..0b785bdfe 100644 --- a/src/libcamera/ipa_interface.cpp +++ b/src/libcamera/ipa_interface.cpp @@ -235,6 +235,20 @@ * \sa libcamera::IPAInterface::init() */ +/** + * \var ipa_context_ops::start + * \brief Start the IPA context + * + * \sa libcamera::IPAInterface::start() + */ + +/** + * \var ipa_context_ops::stop + * \brief Stop the IPA context + * + * \sa libcamera::IPAInterface::stop() + */ + /** * \var ipa_context_ops::register_callbacks * \brief Register callback operation from the IPA to the pipeline handler @@ -412,6 +426,24 @@ namespace libcamera { * \brief Initialise the IPAInterface */ +/** + * \fn IPAInterface::start() + * \brief Start the IPA + * + * This method informs the IPA module that the camera is about to be started. + * The IPA module shall prepare any resources it needs to operate. + * + * \return 0 on success or a negative error code otherwise + */ + +/** + * \fn IPAInterface::stop() + * \brief Stop the IPA + * + * This method informs the IPA module that the camera is stopped. The IPA module + * shall release resources prepared in start(). + */ + /** * \fn IPAInterface::configure() * \brief Configure the IPA stream and sensor settings diff --git a/src/libcamera/proxy/ipa_proxy_linux.cpp b/src/libcamera/proxy/ipa_proxy_linux.cpp index c7218fb47..2aa80b946 100644 --- a/src/libcamera/proxy/ipa_proxy_linux.cpp +++ b/src/libcamera/proxy/ipa_proxy_linux.cpp @@ -27,6 +27,8 @@ public: ~IPAProxyLinux(); int init() override { return 0; } + int start() override { return 0; } + void stop() override {} void configure(const std::map &streamConfig, const std::map &entityControls) override {} void mapBuffers(const std::vector &buffers) override {} diff --git a/test/ipa/ipa_interface_test.cpp b/test/ipa/ipa_interface_test.cpp index cafc249bb..22f9ca41e 100644 --- a/test/ipa/ipa_interface_test.cpp +++ b/test/ipa/ipa_interface_test.cpp @@ -109,6 +109,28 @@ protected: return TestFail; } + /* Test start of IPA module. */ + ipa_->start(); + timer.start(1000); + while (timer.isRunning() && trace_ != IPAOperationStart) + dispatcher->processEvents(); + + if (trace_ != IPAOperationStart) { + cerr << "Failed to test IPA start sequence" << endl; + return TestFail; + } + + /* Test stop of IPA module. */ + ipa_->stop(); + timer.start(1000); + while (timer.isRunning() && trace_ != IPAOperationStop) + dispatcher->processEvents(); + + if (trace_ != IPAOperationStop) { + cerr << "Failed to test IPA stop sequence" << endl; + return TestFail; + } + return TestPass; } diff --git a/test/ipa/ipa_wrappers_test.cpp b/test/ipa/ipa_wrappers_test.cpp index 1ae178116..fae1d56b6 100644 --- a/test/ipa/ipa_wrappers_test.cpp +++ b/test/ipa/ipa_wrappers_test.cpp @@ -27,6 +27,8 @@ using namespace std; enum Operation { Op_init, + Op_start, + Op_stop, Op_configure, Op_mapBuffers, Op_unmapBuffers, @@ -47,6 +49,17 @@ public: return 0; } + int start() override + { + report(Op_start, TestPass); + return 0; + } + + void stop() override + { + report(Op_stop, TestPass); + } + void configure(const std::map &streamConfig, const std::map &entityControls) override { @@ -323,12 +336,26 @@ protected: return TestFail; /* - * Test init() last to ensure nothing in the wrappers or - * serializer depends on init() being called first. + * Test init(), start() and stop() last to ensure nothing in the + * wrappers or serializer depends on them being called first. */ ret = INVOKE(init); - if (ret == TestFail) + if (ret == TestFail) { + cerr << "Failed to run init()"; return TestFail; + } + + ret = INVOKE(start); + if (ret == TestFail) { + cerr << "Failed to run start()"; + return TestFail; + } + + ret = INVOKE(stop); + if (ret == TestFail) { + cerr << "Failed to run stop()"; + return TestFail; + } return TestPass; }