Message ID | 20210811070305.27572-1-vedantparanjape160201@gmail.com |
---|---|
State | Superseded |
Headers | show |
Series |
|
Related | show |
Hi Vedant, On 11/08/2021 08:03, Vedant Paranjape wrote: > This patch adds a test to test if single stream using > libcamera's gstreamer element works. > > Signed-off-by: Vedant Paranjape <vedantparanjape160201@gmail.com> > Reviewed-by: Paul Elder <paul.elder@ideasonboard.com> Is there anything specific needed to run this? When I ran it here I get: 12/66 libcamera:gstreamer / single_stream_test FAIL 0.01s (exit status 255 or signal 127 SIGinvalid) stderr: Not all elements could be created. > --- > .../gstreamer_single_stream_test.cpp | 116 ++++++++++++++++++ > test/gstreamer/meson.build | 19 +++ > test/meson.build | 1 + > 3 files changed, 136 insertions(+) > create mode 100644 test/gstreamer/gstreamer_single_stream_test.cpp > create mode 100644 test/gstreamer/meson.build > > diff --git a/test/gstreamer/gstreamer_single_stream_test.cpp b/test/gstreamer/gstreamer_single_stream_test.cpp > new file mode 100644 > index 00000000..c19da3f2 > --- /dev/null > +++ b/test/gstreamer/gstreamer_single_stream_test.cpp > @@ -0,0 +1,116 @@ > +#include <gst/gst.h> > +#include <iostream> > + > +#include "test.h" > + > +using namespace std; > + > +class GstreamerSingleStreamTest : public Test > +{ > +protected: > + int init() override > + { > + /* Initialize GStreamer */ > + GError *err_init = nullptr; > + if (!gst_init_check(nullptr, nullptr, &err_init)) { > + g_printerr("Could not initialize GStreamer: %s\n", > + err_init ? err_init->message : "unknown error"); > + if (err_init) > + g_error_free(err_init); > + > + return TestFail; > + } > + > + /* Create the elements */ > + libcamera_src_ = gst_element_factory_make("libcamerasrc", "libcamera"); > + convert0_ = gst_element_factory_make("videoconvert", "convert0"); > + sink0_ = gst_element_factory_make("autovideosink", "sink0"); > + > + /* Create the empty pipeline_ */ > + pipeline_ = gst_pipeline_new("test-pipeline"); > + > + if (!pipeline_ || !convert0_ || !sink0_ || !libcamera_src_) { > + g_printerr("Not all elements could be created.\n"); > + return TestFail; > + } > + > + return TestPass; > + } > + > + void cleanup() override > + { > + gst_message_unref(msg_); > + gst_object_unref(bus_); > + gst_element_set_state(pipeline_, GST_STATE_NULL); > + gst_object_unref(pipeline_); > + } > + > + int run() override > + { > + /* Build the pipeline */ > + gst_bin_add_many(GST_BIN(pipeline_), libcamera_src_, convert0_, sink0_, NULL); > + if (gst_element_link_many(libcamera_src_, convert0_, sink0_, NULL) != TRUE) { > + g_printerr("Elements could not be linked.\n"); > + gst_object_unref(pipeline_); > + return TestFail; > + } > + > + /* Start playing */ > + ret_ = gst_element_set_state(pipeline_, GST_STATE_PLAYING); > + if (ret_ == GST_STATE_CHANGE_FAILURE) { > + g_printerr("Unable to set the pipeline to the playing state.\n"); > + gst_object_unref(pipeline_); > + return TestFail; > + } > + > + /* Wait until error or EOS or timeout after 2 seconds*/ > + GstClockTime timeout = 2000000000; > + bus_ = gst_element_get_bus(pipeline_); > + msg_ = gst_bus_timed_pop_filtered(bus_, timeout, > + GstMessageType((uint)GST_MESSAGE_ERROR | (uint)GST_MESSAGE_EOS)); > + > + /* Parse error message */ > + if (msg_ == NULL) > + return TestPass; > + > + switch (GST_MESSAGE_TYPE(msg_)) { > + case GST_MESSAGE_ERROR: > + GstreamerPrintError(msg_); > + return TestFail; > + break; > + case GST_MESSAGE_EOS: > + g_print("End-Of-Stream reached.\n"); > + return TestFail; > + break; > + default: > + g_printerr("Unexpected message received.\n"); > + return TestFail; > + break; > + } > + > + return TestPass; > + } > + > +private: > + GstElement *pipeline_, *libcamera_src_, *convert0_, *sink0_; > + GstBus *bus_; > + GstMessage *msg_; > + GstStateChangeReturn ret_; > + > + void GstreamerPrintError(GstMessage *msg) > + { > + GError *err; > + gchar *debug_info; > + > + gst_message_parse_error(msg, &err, &debug_info); > + g_printerr("Error received from element %s: %s\n", > + GST_OBJECT_NAME(msg->src), err->message); > + g_printerr("Debugging information: %s\n", > + debug_info ? debug_info : "none"); > + g_clear_error(&err); > + g_free(debug_info); > + } > +}; > + > +TEST_REGISTER(GstreamerSingleStreamTest) > + > diff --git a/test/gstreamer/meson.build b/test/gstreamer/meson.build > new file mode 100644 > index 00000000..b99aa0da > --- /dev/null > +++ b/test/gstreamer/meson.build > @@ -0,0 +1,19 @@ > +# SPDX-License-Identifier: CC0-1.0 > + > +if not gst_enabled > + subdir_done() > +endif > + > +gstreamer_tests = [ > + ['single_stream_test', 'gstreamer_single_stream_test.cpp'], > +] > +gstreamer_dep = dependency('gstreamer-1.0', required: true) > + > +foreach t : gstreamer_tests > + exe = executable(t[0], t[1], > + dependencies : [libcamera_private, gstreamer_dep], > + link_with : test_libraries, > + include_directories : test_includes_internal) > + > + test(t[0], exe, suite : 'gstreamer', is_parallel : false) > +endforeach > diff --git a/test/meson.build b/test/meson.build > index 3bceb5df..d0466f17 100644 > --- a/test/meson.build > +++ b/test/meson.build > @@ -11,6 +11,7 @@ subdir('libtest') > > subdir('camera') > subdir('controls') > +subdir('gstreamer') > subdir('ipa') > subdir('ipc') > subdir('log') >
Hi Again, On 11/08/2021 13:47, Kieran Bingham wrote: > Hi Vedant, > > On 11/08/2021 08:03, Vedant Paranjape wrote: >> This patch adds a test to test if single stream using >> libcamera's gstreamer element works. >> >> Signed-off-by: Vedant Paranjape <vedantparanjape160201@gmail.com> >> Reviewed-by: Paul Elder <paul.elder@ideasonboard.com> > > Is there anything specific needed to run this? > > When I ran it here I get: > > > 12/66 libcamera:gstreamer / single_stream_test > FAIL 0.01s (exit status 255 or signal 127 SIGinvalid) > stderr: > Not all elements could be created. Somehow we need to export the GST_PLUGIN_PATH from the build to the test when it is run. Manually running the test, while manually setting the path gives: > GST_PLUGIN_PATH=./build/src/gstreamer/ ./build/test/gstreamer/single_stream_test > [322:51:39.768296143] [2459570] INFO IPAManager ipa_manager.cpp:138 libcamera is not installed. Adding '/home/kbingham/iob/libcamera/chromeos/src/third_party/libcamera/build/src/ipa' to the IPA search path > [322:51:39.769209245] [2459570] INFO Camera camera_manager.cpp:294 libcamera v0.0.0+2918-15014c37 > [322:51:39.772516638] [2459575] INFO V4L2 v4l2_subdevice.cpp:242 'Sensor B': Using /dev/v4l-subdev1 > [322:51:39.773277255] [2459575] WARN CameraSensorProperties camera_sensor_properties.cpp:123 No static properties available for 'Sensor B' > [322:51:39.773290289] [2459575] WARN CameraSensorProperties camera_sensor_properties.cpp:125 Please consider updating the camera sensor properties database > [322:51:39.773298484] [2459575] WARN CameraSensor camera_sensor.cpp:403 'Sensor B': Failed to retrieve the camera location > [322:51:39.773317911] [2459575] INFO V4L2 v4l2_subdevice.cpp:242 'Debayer B': Using /dev/v4l-subdev3 > [322:51:39.773365811] [2459575] INFO V4L2 v4l2_subdevice.cpp:242 'Scaler': Using /dev/v4l-subdev5 > [322:51:39.773441643] [2459575] WARN IPAManager ipa_manager.cpp:280 IPA module /home/kbingham/iob/libcamera/chromeos/src/third_party/libcamera/build/src/ipa/vimc/ipa_vimc.so signature regarded as valid > [322:51:39.773731977] [2459575] INFO IPAProxy ipa_proxy.cpp:130 libcamera is not installed. Loading IPA configuration from '/home/kbingham/iob/libcamera/chromeos/src/third_party/libcamera/src/ipa/vimc/data' > [322:51:39.838754646] [2459576] INFO Camera camera.cpp:873 configuring streams: (0) 156x120-BGR888 > > (single_stream_test:2459570): GStreamer-CRITICAL **: 13:51:14.445: gst_mini_object_unref: assertion 'mini_object != NULL' failed But even that only showed me a black box that appeared, and then seemed to disappear again. We might also want to run the automated tests on systems without a display, so pop windows might not work there. But I'd be tempted to say we can deal with that when we find an actual need for that, and keep the visual test, as ... (if It works, and shows an image) it would be a nice visual confirmation while running the tests. Otherwise, perhaps a pipeline that generates an output PNG or encoded video might be required, or even just a null sink if that's possible? But that can be later anyway. -- Kieran >> --- >> .../gstreamer_single_stream_test.cpp | 116 ++++++++++++++++++ >> test/gstreamer/meson.build | 19 +++ >> test/meson.build | 1 + >> 3 files changed, 136 insertions(+) >> create mode 100644 test/gstreamer/gstreamer_single_stream_test.cpp >> create mode 100644 test/gstreamer/meson.build >> >> diff --git a/test/gstreamer/gstreamer_single_stream_test.cpp b/test/gstreamer/gstreamer_single_stream_test.cpp >> new file mode 100644 >> index 00000000..c19da3f2 >> --- /dev/null >> +++ b/test/gstreamer/gstreamer_single_stream_test.cpp >> @@ -0,0 +1,116 @@ >> +#include <gst/gst.h> >> +#include <iostream> >> + >> +#include "test.h" >> + >> +using namespace std; >> + >> +class GstreamerSingleStreamTest : public Test >> +{ >> +protected: >> + int init() override >> + { >> + /* Initialize GStreamer */ >> + GError *err_init = nullptr; >> + if (!gst_init_check(nullptr, nullptr, &err_init)) { >> + g_printerr("Could not initialize GStreamer: %s\n", >> + err_init ? err_init->message : "unknown error"); >> + if (err_init) >> + g_error_free(err_init); >> + >> + return TestFail; >> + } >> + >> + /* Create the elements */ >> + libcamera_src_ = gst_element_factory_make("libcamerasrc", "libcamera"); >> + convert0_ = gst_element_factory_make("videoconvert", "convert0"); >> + sink0_ = gst_element_factory_make("autovideosink", "sink0"); >> + >> + /* Create the empty pipeline_ */ >> + pipeline_ = gst_pipeline_new("test-pipeline"); >> + >> + if (!pipeline_ || !convert0_ || !sink0_ || !libcamera_src_) { >> + g_printerr("Not all elements could be created.\n"); >> + return TestFail; >> + } >> + >> + return TestPass; >> + } >> + >> + void cleanup() override >> + { >> + gst_message_unref(msg_); >> + gst_object_unref(bus_); >> + gst_element_set_state(pipeline_, GST_STATE_NULL); >> + gst_object_unref(pipeline_); >> + } >> + >> + int run() override >> + { >> + /* Build the pipeline */ >> + gst_bin_add_many(GST_BIN(pipeline_), libcamera_src_, convert0_, sink0_, NULL); >> + if (gst_element_link_many(libcamera_src_, convert0_, sink0_, NULL) != TRUE) { >> + g_printerr("Elements could not be linked.\n"); >> + gst_object_unref(pipeline_); >> + return TestFail; >> + } >> + >> + /* Start playing */ >> + ret_ = gst_element_set_state(pipeline_, GST_STATE_PLAYING); >> + if (ret_ == GST_STATE_CHANGE_FAILURE) { >> + g_printerr("Unable to set the pipeline to the playing state.\n"); >> + gst_object_unref(pipeline_); >> + return TestFail; >> + } >> + >> + /* Wait until error or EOS or timeout after 2 seconds*/ >> + GstClockTime timeout = 2000000000; >> + bus_ = gst_element_get_bus(pipeline_); >> + msg_ = gst_bus_timed_pop_filtered(bus_, timeout, >> + GstMessageType((uint)GST_MESSAGE_ERROR | (uint)GST_MESSAGE_EOS)); >> + >> + /* Parse error message */ >> + if (msg_ == NULL) >> + return TestPass; >> + >> + switch (GST_MESSAGE_TYPE(msg_)) { >> + case GST_MESSAGE_ERROR: >> + GstreamerPrintError(msg_); >> + return TestFail; >> + break; >> + case GST_MESSAGE_EOS: >> + g_print("End-Of-Stream reached.\n"); >> + return TestFail; >> + break; >> + default: >> + g_printerr("Unexpected message received.\n"); >> + return TestFail; >> + break; >> + } >> + >> + return TestPass; >> + } >> + >> +private: >> + GstElement *pipeline_, *libcamera_src_, *convert0_, *sink0_; >> + GstBus *bus_; >> + GstMessage *msg_; >> + GstStateChangeReturn ret_; >> + >> + void GstreamerPrintError(GstMessage *msg) >> + { >> + GError *err; >> + gchar *debug_info; >> + >> + gst_message_parse_error(msg, &err, &debug_info); >> + g_printerr("Error received from element %s: %s\n", >> + GST_OBJECT_NAME(msg->src), err->message); >> + g_printerr("Debugging information: %s\n", >> + debug_info ? debug_info : "none"); >> + g_clear_error(&err); >> + g_free(debug_info); >> + } >> +}; >> + >> +TEST_REGISTER(GstreamerSingleStreamTest) >> + >> diff --git a/test/gstreamer/meson.build b/test/gstreamer/meson.build >> new file mode 100644 >> index 00000000..b99aa0da >> --- /dev/null >> +++ b/test/gstreamer/meson.build >> @@ -0,0 +1,19 @@ >> +# SPDX-License-Identifier: CC0-1.0 >> + >> +if not gst_enabled >> + subdir_done() >> +endif >> + >> +gstreamer_tests = [ >> + ['single_stream_test', 'gstreamer_single_stream_test.cpp'], >> +] >> +gstreamer_dep = dependency('gstreamer-1.0', required: true) >> + >> +foreach t : gstreamer_tests >> + exe = executable(t[0], t[1], >> + dependencies : [libcamera_private, gstreamer_dep], >> + link_with : test_libraries, >> + include_directories : test_includes_internal) >> + >> + test(t[0], exe, suite : 'gstreamer', is_parallel : false) >> +endforeach >> diff --git a/test/meson.build b/test/meson.build >> index 3bceb5df..d0466f17 100644 >> --- a/test/meson.build >> +++ b/test/meson.build >> @@ -11,6 +11,7 @@ subdir('libtest') >> >> subdir('camera') >> subdir('controls') >> +subdir('gstreamer') >> subdir('ipa') >> subdir('ipc') >> subdir('log') >>
Hi, On Wed, Aug 11, 2021 at 01:56:08PM +0100, Kieran Bingham wrote: > On 11/08/2021 13:47, Kieran Bingham wrote: > > On 11/08/2021 08:03, Vedant Paranjape wrote: > >> This patch adds a test to test if single stream using > >> libcamera's gstreamer element works. > >> > >> Signed-off-by: Vedant Paranjape <vedantparanjape160201@gmail.com> > >> Reviewed-by: Paul Elder <paul.elder@ideasonboard.com> > > > > Is there anything specific needed to run this? > > > > When I ran it here I get: > > > > > > 12/66 libcamera:gstreamer / single_stream_test > > FAIL 0.01s (exit status 255 or signal 127 SIGinvalid) > > stderr: > > Not all elements could be created. > > Somehow we need to export the GST_PLUGIN_PATH from the build to the test > when it is run. I've run into the same issue. This needs to be fixed, as otherwise running 'ninja test' will fail. > Manually running the test, while manually setting the path gives: > > > > GST_PLUGIN_PATH=./build/src/gstreamer/ ./build/test/gstreamer/single_stream_test > > [322:51:39.768296143] [2459570] INFO IPAManager ipa_manager.cpp:138 libcamera is not installed. Adding '/home/kbingham/iob/libcamera/chromeos/src/third_party/libcamera/build/src/ipa' to the IPA search path > > [322:51:39.769209245] [2459570] INFO Camera camera_manager.cpp:294 libcamera v0.0.0+2918-15014c37 > > [322:51:39.772516638] [2459575] INFO V4L2 v4l2_subdevice.cpp:242 'Sensor B': Using /dev/v4l-subdev1 > > [322:51:39.773277255] [2459575] WARN CameraSensorProperties camera_sensor_properties.cpp:123 No static properties available for 'Sensor B' > > [322:51:39.773290289] [2459575] WARN CameraSensorProperties camera_sensor_properties.cpp:125 Please consider updating the camera sensor properties database > > [322:51:39.773298484] [2459575] WARN CameraSensor camera_sensor.cpp:403 'Sensor B': Failed to retrieve the camera location > > [322:51:39.773317911] [2459575] INFO V4L2 v4l2_subdevice.cpp:242 'Debayer B': Using /dev/v4l-subdev3 > > [322:51:39.773365811] [2459575] INFO V4L2 v4l2_subdevice.cpp:242 'Scaler': Using /dev/v4l-subdev5 > > [322:51:39.773441643] [2459575] WARN IPAManager ipa_manager.cpp:280 IPA module /home/kbingham/iob/libcamera/chromeos/src/third_party/libcamera/build/src/ipa/vimc/ipa_vimc.so signature regarded as valid > > [322:51:39.773731977] [2459575] INFO IPAProxy ipa_proxy.cpp:130 libcamera is not installed. Loading IPA configuration from '/home/kbingham/iob/libcamera/chromeos/src/third_party/libcamera/src/ipa/vimc/data' > > [322:51:39.838754646] [2459576] INFO Camera camera.cpp:873 configuring streams: (0) 156x120-BGR888 > > > > (single_stream_test:2459570): GStreamer-CRITICAL **: 13:51:14.445: gst_mini_object_unref: assertion 'mini_object != NULL' failed > > But even that only showed me a black box that appeared, and then seemed > to disappear again. > > We might also want to run the automated tests on systems without a > display, so pop windows might not work there. > > But I'd be tempted to say we can deal with that when we find an actual > need for that, and keep the visual test, as ... (if It works, and shows > an image) it would be a nice visual confirmation while running the tests. > > Otherwise, perhaps a pipeline that generates an output PNG or encoded > video might be required, or even just a null sink if that's possible? A null sink would be better, as I already run tests on headless systems. It may be as simple as s/autovideosink/fakevideosink/ in the code below, so I think we should already address that. > But that can be later anyway. > > >> --- > >> .../gstreamer_single_stream_test.cpp | 116 ++++++++++++++++++ > >> test/gstreamer/meson.build | 19 +++ > >> test/meson.build | 1 + > >> 3 files changed, 136 insertions(+) > >> create mode 100644 test/gstreamer/gstreamer_single_stream_test.cpp > >> create mode 100644 test/gstreamer/meson.build > >> > >> diff --git a/test/gstreamer/gstreamer_single_stream_test.cpp b/test/gstreamer/gstreamer_single_stream_test.cpp > >> new file mode 100644 > >> index 00000000..c19da3f2 > >> --- /dev/null > >> +++ b/test/gstreamer/gstreamer_single_stream_test.cpp > >> @@ -0,0 +1,116 @@ > >> +#include <gst/gst.h> > >> +#include <iostream> > >> + > >> +#include "test.h" > >> + > >> +using namespace std; > >> + > >> +class GstreamerSingleStreamTest : public Test > >> +{ > >> +protected: > >> + int init() override > >> + { > >> + /* Initialize GStreamer */ > >> + GError *err_init = nullptr; > >> + if (!gst_init_check(nullptr, nullptr, &err_init)) { > >> + g_printerr("Could not initialize GStreamer: %s\n", > >> + err_init ? err_init->message : "unknown error"); > >> + if (err_init) > >> + g_error_free(err_init); > >> + > >> + return TestFail; > >> + } > >> + > >> + /* Create the elements */ > >> + libcamera_src_ = gst_element_factory_make("libcamerasrc", "libcamera"); > >> + convert0_ = gst_element_factory_make("videoconvert", "convert0"); > >> + sink0_ = gst_element_factory_make("autovideosink", "sink0"); > >> + > >> + /* Create the empty pipeline_ */ > >> + pipeline_ = gst_pipeline_new("test-pipeline"); > >> + > >> + if (!pipeline_ || !convert0_ || !sink0_ || !libcamera_src_) { > >> + g_printerr("Not all elements could be created.\n"); > >> + return TestFail; > >> + } > >> + > >> + return TestPass; > >> + } > >> + > >> + void cleanup() override > >> + { > >> + gst_message_unref(msg_); > >> + gst_object_unref(bus_); > >> + gst_element_set_state(pipeline_, GST_STATE_NULL); > >> + gst_object_unref(pipeline_); > >> + } > >> + > >> + int run() override > >> + { > >> + /* Build the pipeline */ > >> + gst_bin_add_many(GST_BIN(pipeline_), libcamera_src_, convert0_, sink0_, NULL); > >> + if (gst_element_link_many(libcamera_src_, convert0_, sink0_, NULL) != TRUE) { > >> + g_printerr("Elements could not be linked.\n"); > >> + gst_object_unref(pipeline_); > >> + return TestFail; > >> + } > >> + > >> + /* Start playing */ > >> + ret_ = gst_element_set_state(pipeline_, GST_STATE_PLAYING); > >> + if (ret_ == GST_STATE_CHANGE_FAILURE) { > >> + g_printerr("Unable to set the pipeline to the playing state.\n"); > >> + gst_object_unref(pipeline_); > >> + return TestFail; > >> + } > >> + > >> + /* Wait until error or EOS or timeout after 2 seconds*/ > >> + GstClockTime timeout = 2000000000; > >> + bus_ = gst_element_get_bus(pipeline_); > >> + msg_ = gst_bus_timed_pop_filtered(bus_, timeout, > >> + GstMessageType((uint)GST_MESSAGE_ERROR | (uint)GST_MESSAGE_EOS)); > >> + > >> + /* Parse error message */ > >> + if (msg_ == NULL) > >> + return TestPass; > >> + > >> + switch (GST_MESSAGE_TYPE(msg_)) { > >> + case GST_MESSAGE_ERROR: > >> + GstreamerPrintError(msg_); > >> + return TestFail; > >> + break; > >> + case GST_MESSAGE_EOS: > >> + g_print("End-Of-Stream reached.\n"); > >> + return TestFail; > >> + break; > >> + default: > >> + g_printerr("Unexpected message received.\n"); > >> + return TestFail; > >> + break; > >> + } > >> + > >> + return TestPass; > >> + } > >> + > >> +private: > >> + GstElement *pipeline_, *libcamera_src_, *convert0_, *sink0_; > >> + GstBus *bus_; > >> + GstMessage *msg_; > >> + GstStateChangeReturn ret_; > >> + > >> + void GstreamerPrintError(GstMessage *msg) > >> + { > >> + GError *err; > >> + gchar *debug_info; > >> + > >> + gst_message_parse_error(msg, &err, &debug_info); > >> + g_printerr("Error received from element %s: %s\n", > >> + GST_OBJECT_NAME(msg->src), err->message); > >> + g_printerr("Debugging information: %s\n", > >> + debug_info ? debug_info : "none"); > >> + g_clear_error(&err); > >> + g_free(debug_info); > >> + } > >> +}; > >> + > >> +TEST_REGISTER(GstreamerSingleStreamTest) > >> + > >> diff --git a/test/gstreamer/meson.build b/test/gstreamer/meson.build > >> new file mode 100644 > >> index 00000000..b99aa0da > >> --- /dev/null > >> +++ b/test/gstreamer/meson.build > >> @@ -0,0 +1,19 @@ > >> +# SPDX-License-Identifier: CC0-1.0 > >> + > >> +if not gst_enabled > >> + subdir_done() > >> +endif > >> + > >> +gstreamer_tests = [ > >> + ['single_stream_test', 'gstreamer_single_stream_test.cpp'], > >> +] > >> +gstreamer_dep = dependency('gstreamer-1.0', required: true) > >> + > >> +foreach t : gstreamer_tests > >> + exe = executable(t[0], t[1], > >> + dependencies : [libcamera_private, gstreamer_dep], > >> + link_with : test_libraries, > >> + include_directories : test_includes_internal) > >> + > >> + test(t[0], exe, suite : 'gstreamer', is_parallel : false) > >> +endforeach > >> diff --git a/test/meson.build b/test/meson.build > >> index 3bceb5df..d0466f17 100644 > >> --- a/test/meson.build > >> +++ b/test/meson.build > >> @@ -11,6 +11,7 @@ subdir('libtest') > >> > >> subdir('camera') > >> subdir('controls') > >> +subdir('gstreamer') > >> subdir('ipa') > >> subdir('ipc') > >> subdir('log')
Hi Laurent, Kieran On Wed, Aug 11, 2021 at 6:34 PM Laurent Pinchart < laurent.pinchart@ideasonboard.com> wrote: > Hi, > > On Wed, Aug 11, 2021 at 01:56:08PM +0100, Kieran Bingham wrote: > > On 11/08/2021 13:47, Kieran Bingham wrote: > > > On 11/08/2021 08:03, Vedant Paranjape wrote: > > >> This patch adds a test to test if single stream using > > >> libcamera's gstreamer element works. > > >> > > >> Signed-off-by: Vedant Paranjape <vedantparanjape160201@gmail.com> > > >> Reviewed-by: Paul Elder <paul.elder@ideasonboard.com> > > > > > > Is there anything specific needed to run this? > > > > > > When I ran it here I get: > > > > > > > > > 12/66 libcamera:gstreamer / single_stream_test > > > FAIL 0.01s (exit status 255 or signal 127 SIGinvalid) > > > stderr: > > > Not all elements could be created. > > > > Somehow we need to export the GST_PLUGIN_PATH from the build to the test > > when it is run. > > I've run into the same issue. This needs to be fixed, as otherwise > running 'ninja test' will fail. > I think you need to set the path or install libcamera in root, not sure what needs to be fixed. > Manually running the test, while manually setting the path gives: > > > > > > > GST_PLUGIN_PATH=./build/src/gstreamer/ > ./build/test/gstreamer/single_stream_test > > > [322:51:39.768296143] [2459570] INFO IPAManager ipa_manager.cpp:138 > libcamera is not installed. Adding > '/home/kbingham/iob/libcamera/chromeos/src/third_party/libcamera/build/src/ipa' > to the IPA search path > > > [322:51:39.769209245] [2459570] INFO Camera camera_manager.cpp:294 > libcamera v0.0.0+2918-15014c37 > > > [322:51:39.772516638] [2459575] INFO V4L2 v4l2_subdevice.cpp:242 > 'Sensor B': Using /dev/v4l-subdev1 > > > [322:51:39.773277255] [2459575] WARN CameraSensorProperties > camera_sensor_properties.cpp:123 No static properties available for 'Sensor > B' > > > [322:51:39.773290289] [2459575] WARN CameraSensorProperties > camera_sensor_properties.cpp:125 Please consider updating the camera sensor > properties database > > > [322:51:39.773298484] [2459575] WARN CameraSensor > camera_sensor.cpp:403 'Sensor B': Failed to retrieve the camera location > > > [322:51:39.773317911] [2459575] INFO V4L2 v4l2_subdevice.cpp:242 > 'Debayer B': Using /dev/v4l-subdev3 > > > [322:51:39.773365811] [2459575] INFO V4L2 v4l2_subdevice.cpp:242 > 'Scaler': Using /dev/v4l-subdev5 > > > [322:51:39.773441643] [2459575] WARN IPAManager ipa_manager.cpp:280 > IPA module > /home/kbingham/iob/libcamera/chromeos/src/third_party/libcamera/build/src/ipa/vimc/ipa_vimc.so > signature regarded as valid > > > [322:51:39.773731977] [2459575] INFO IPAProxy ipa_proxy.cpp:130 > libcamera is not installed. Loading IPA configuration from > '/home/kbingham/iob/libcamera/chromeos/src/third_party/libcamera/src/ipa/vimc/data' > > > [322:51:39.838754646] [2459576] INFO Camera camera.cpp:873 > configuring streams: (0) 156x120-BGR888 > > > > > > (single_stream_test:2459570): GStreamer-CRITICAL **: 13:51:14.445: > gst_mini_object_unref: assertion 'mini_object != NULL' failed > > > > But even that only showed me a black box that appeared, and then seemed > > to disappear again. > > > > We might also want to run the automated tests on systems without a > > display, so pop windows might not work there. > > > > But I'd be tempted to say we can deal with that when we find an actual > > need for that, and keep the visual test, as ... (if It works, and shows > > an image) it would be a nice visual confirmation while running the tests. > > > > Otherwise, perhaps a pipeline that generates an output PNG or encoded > > video might be required, or even just a null sink if that's possible? > > A null sink would be better, as I already run tests on headless systems. > It may be as simple as s/autovideosink/fakevideosink/ in the code below, > so I think we should already address that. I tried this, it works, should I sent a new patch with this ? > But that can be later anyway. > > > > >> --- > > >> .../gstreamer_single_stream_test.cpp | 116 > ++++++++++++++++++ > > >> test/gstreamer/meson.build | 19 +++ > > >> test/meson.build | 1 + > > >> 3 files changed, 136 insertions(+) > > >> create mode 100644 test/gstreamer/gstreamer_single_stream_test.cpp > > >> create mode 100644 test/gstreamer/meson.build > > >> > > >> diff --git a/test/gstreamer/gstreamer_single_stream_test.cpp > b/test/gstreamer/gstreamer_single_stream_test.cpp > > >> new file mode 100644 > > >> index 00000000..c19da3f2 > > >> --- /dev/null > > >> +++ b/test/gstreamer/gstreamer_single_stream_test.cpp > > >> @@ -0,0 +1,116 @@ > > >> +#include <gst/gst.h> > > >> +#include <iostream> > > >> + > > >> +#include "test.h" > > >> + > > >> +using namespace std; > > >> + > > >> +class GstreamerSingleStreamTest : public Test > > >> +{ > > >> +protected: > > >> + int init() override > > >> + { > > >> + /* Initialize GStreamer */ > > >> + GError *err_init = nullptr; > > >> + if (!gst_init_check(nullptr, nullptr, &err_init)) { > > >> + g_printerr("Could not initialize GStreamer: %s\n", > > >> + err_init ? err_init->message : "unknown > error"); > > >> + if (err_init) > > >> + g_error_free(err_init); > > >> + > > >> + return TestFail; > > >> + } > > >> + > > >> + /* Create the elements */ > > >> + libcamera_src_ = gst_element_factory_make("libcamerasrc", > "libcamera"); > > >> + convert0_ = gst_element_factory_make("videoconvert", > "convert0"); > > >> + sink0_ = gst_element_factory_make("autovideosink", > "sink0"); > > >> + > > >> + /* Create the empty pipeline_ */ > > >> + pipeline_ = gst_pipeline_new("test-pipeline"); > > >> + > > >> + if (!pipeline_ || !convert0_ || !sink0_ || > !libcamera_src_) { > > >> + g_printerr("Not all elements could be created.\n"); > > >> + return TestFail; > > >> + } > > >> + > > >> + return TestPass; > > >> + } > > >> + > > >> + void cleanup() override > > >> + { > > >> + gst_message_unref(msg_); > > >> + gst_object_unref(bus_); > > >> + gst_element_set_state(pipeline_, GST_STATE_NULL); > > >> + gst_object_unref(pipeline_); > > >> + } > > >> + > > >> + int run() override > > >> + { > > >> + /* Build the pipeline */ > > >> + gst_bin_add_many(GST_BIN(pipeline_), libcamera_src_, > convert0_, sink0_, NULL); > > >> + if (gst_element_link_many(libcamera_src_, convert0_, > sink0_, NULL) != TRUE) { > > >> + g_printerr("Elements could not be linked.\n"); > > >> + gst_object_unref(pipeline_); > > >> + return TestFail; > > >> + } > > >> + > > >> + /* Start playing */ > > >> + ret_ = gst_element_set_state(pipeline_, GST_STATE_PLAYING); > > >> + if (ret_ == GST_STATE_CHANGE_FAILURE) { > > >> + g_printerr("Unable to set the pipeline to the > playing state.\n"); > > >> + gst_object_unref(pipeline_); > > >> + return TestFail; > > >> + } > > >> + > > >> + /* Wait until error or EOS or timeout after 2 seconds*/ > > >> + GstClockTime timeout = 2000000000; > > >> + bus_ = gst_element_get_bus(pipeline_); > > >> + msg_ = gst_bus_timed_pop_filtered(bus_, timeout, > > >> + > GstMessageType((uint)GST_MESSAGE_ERROR | (uint)GST_MESSAGE_EOS)); > > >> + > > >> + /* Parse error message */ > > >> + if (msg_ == NULL) > > >> + return TestPass; > > >> + > > >> + switch (GST_MESSAGE_TYPE(msg_)) { > > >> + case GST_MESSAGE_ERROR: > > >> + GstreamerPrintError(msg_); > > >> + return TestFail; > > >> + break; > > >> + case GST_MESSAGE_EOS: > > >> + g_print("End-Of-Stream reached.\n"); > > >> + return TestFail; > > >> + break; > > >> + default: > > >> + g_printerr("Unexpected message received.\n"); > > >> + return TestFail; > > >> + break; > > >> + } > > >> + > > >> + return TestPass; > > >> + } > > >> + > > >> +private: > > >> + GstElement *pipeline_, *libcamera_src_, *convert0_, *sink0_; > > >> + GstBus *bus_; > > >> + GstMessage *msg_; > > >> + GstStateChangeReturn ret_; > > >> + > > >> + void GstreamerPrintError(GstMessage *msg) > > >> + { > > >> + GError *err; > > >> + gchar *debug_info; > > >> + > > >> + gst_message_parse_error(msg, &err, &debug_info); > > >> + g_printerr("Error received from element %s: %s\n", > > >> + GST_OBJECT_NAME(msg->src), err->message); > > >> + g_printerr("Debugging information: %s\n", > > >> + debug_info ? debug_info : "none"); > > >> + g_clear_error(&err); > > >> + g_free(debug_info); > > >> + } > > >> +}; > > >> + > > >> +TEST_REGISTER(GstreamerSingleStreamTest) > > >> + > > >> diff --git a/test/gstreamer/meson.build b/test/gstreamer/meson.build > > >> new file mode 100644 > > >> index 00000000..b99aa0da > > >> --- /dev/null > > >> +++ b/test/gstreamer/meson.build > > >> @@ -0,0 +1,19 @@ > > >> +# SPDX-License-Identifier: CC0-1.0 > > >> + > > >> +if not gst_enabled > > >> + subdir_done() > > >> +endif > > >> + > > >> +gstreamer_tests = [ > > >> + ['single_stream_test', 'gstreamer_single_stream_test.cpp'], > > >> +] > > >> +gstreamer_dep = dependency('gstreamer-1.0', required: true) > > >> + > > >> +foreach t : gstreamer_tests > > >> + exe = executable(t[0], t[1], > > >> + dependencies : [libcamera_private, > gstreamer_dep], > > >> + link_with : test_libraries, > > >> + include_directories : test_includes_internal) > > >> + > > >> + test(t[0], exe, suite : 'gstreamer', is_parallel : false) > > >> +endforeach > > >> diff --git a/test/meson.build b/test/meson.build > > >> index 3bceb5df..d0466f17 100644 > > >> --- a/test/meson.build > > >> +++ b/test/meson.build > > >> @@ -11,6 +11,7 @@ subdir('libtest') > > >> > > >> subdir('camera') > > >> subdir('controls') > > >> +subdir('gstreamer') > > >> subdir('ipa') > > >> subdir('ipc') > > >> subdir('log') > > -- > Regards, > > Laurent Pinchart > Regards, *Vedant Paranjape*
Hi Vedant, On Wed, Aug 11, 2021 at 07:13:40PM +0530, Vedant Paranjape wrote: > On Wed, Aug 11, 2021 at 6:34 PM Laurent Pinchart wrote: > > On Wed, Aug 11, 2021 at 01:56:08PM +0100, Kieran Bingham wrote: > > > On 11/08/2021 13:47, Kieran Bingham wrote: > > > > On 11/08/2021 08:03, Vedant Paranjape wrote: > > > >> This patch adds a test to test if single stream using > > > >> libcamera's gstreamer element works. > > > >> > > > >> Signed-off-by: Vedant Paranjape <vedantparanjape160201@gmail.com> > > > >> Reviewed-by: Paul Elder <paul.elder@ideasonboard.com> > > > > > > > > Is there anything specific needed to run this? > > > > > > > > When I ran it here I get: > > > > > > > > > > > > 12/66 libcamera:gstreamer / single_stream_test > > > > FAIL 0.01s (exit status 255 or signal 127 SIGinvalid) > > > > stderr: > > > > Not all elements could be created. > > > > > > Somehow we need to export the GST_PLUGIN_PATH from the build to the test > > > when it is run. > > > > I've run into the same issue. This needs to be fixed, as otherwise > > running 'ninja test' will fail. > > I think you need to set the path or install libcamera in root, not sure > what needs to be fixed. That's the whole point, it has to run without installing, and without setting an environment variable. The following has to work without any test failure: git clone https://git.libcamera.org/libcamera/libcamera.git/ cd libcamera mkdir build cd build meson setup .. ninja ninja test One option is to set the environment variable (or use a corresponding GStreamer C API, which would be better) from within the test. > > Manually running the test, while manually setting the path gives: > > > > > > GST_PLUGIN_PATH=./build/src/gstreamer/ ./build/test/gstreamer/single_stream_test > > > > [322:51:39.768296143] [2459570] INFO IPAManager ipa_manager.cpp:138 libcamera is not installed. Adding '/home/kbingham/iob/libcamera/chromeos/src/third_party/libcamera/build/src/ipa' to the IPA search path > > > > [322:51:39.769209245] [2459570] INFO Camera camera_manager.cpp:294 libcamera v0.0.0+2918-15014c37 > > > > [322:51:39.772516638] [2459575] INFO V4L2 v4l2_subdevice.cpp:242 'Sensor B': Using /dev/v4l-subdev1 > > > > [322:51:39.773277255] [2459575] WARN CameraSensorProperties camera_sensor_properties.cpp:123 No static properties available for 'Sensor B' > > > > [322:51:39.773290289] [2459575] WARN CameraSensorProperties camera_sensor_properties.cpp:125 Please consider updating the camera sensor properties database > > > > [322:51:39.773298484] [2459575] WARN CameraSensor camera_sensor.cpp:403 'Sensor B': Failed to retrieve the camera location > > > > [322:51:39.773317911] [2459575] INFO V4L2 v4l2_subdevice.cpp:242 'Debayer B': Using /dev/v4l-subdev3 > > > > [322:51:39.773365811] [2459575] INFO V4L2 v4l2_subdevice.cpp:242 'Scaler': Using /dev/v4l-subdev5 > > > > [322:51:39.773441643] [2459575] WARN IPAManager ipa_manager.cpp:280 IPA module /home/kbingham/iob/libcamera/chromeos/src/third_party/libcamera/build/src/ipa/vimc/ipa_vimc.so signature regarded as valid > > > > [322:51:39.773731977] [2459575] INFO IPAProxy ipa_proxy.cpp:130 libcamera is not installed. Loading IPA configuration from '/home/kbingham/iob/libcamera/chromeos/src/third_party/libcamera/src/ipa/vimc/data' > > > > [322:51:39.838754646] [2459576] INFO Camera camera.cpp:873 configuring streams: (0) 156x120-BGR888 > > > > > > > > (single_stream_test:2459570): GStreamer-CRITICAL **: 13:51:14.445: gst_mini_object_unref: assertion 'mini_object != NULL' failed Additionally, it would be nice if the test returned an error gracefully in this case, instead of crashing with a failed assertion. Error handling is important. > > > But even that only showed me a black box that appeared, and then seemed > > > to disappear again. > > > > > > We might also want to run the automated tests on systems without a > > > display, so pop windows might not work there. > > > > > > But I'd be tempted to say we can deal with that when we find an actual > > > need for that, and keep the visual test, as ... (if It works, and shows > > > an image) it would be a nice visual confirmation while running the tests. > > > > > > Otherwise, perhaps a pipeline that generates an output PNG or encoded > > > video might be required, or even just a null sink if that's possible? > > > > A null sink would be better, as I already run tests on headless systems. > > It may be as simple as s/autovideosink/fakevideosink/ in the code below, > > so I think we should already address that. > > I tried this, it works, should I sent a new patch with this ? Yes, please do this in v6. While at it, could you please run the test under valgrind, to ensure there's no memory leak (at least no memory leak caused by the test, leaks in third party libraries themselves, such as libudev, are not our fault). > > But that can be later anyway. > > > > > >> --- > > > >> .../gstreamer_single_stream_test.cpp | 116 ++++++++++++++++++ > > > >> test/gstreamer/meson.build | 19 +++ > > > >> test/meson.build | 1 + > > > >> 3 files changed, 136 insertions(+) > > > >> create mode 100644 test/gstreamer/gstreamer_single_stream_test.cpp > > > >> create mode 100644 test/gstreamer/meson.build > > > >> > > > >> diff --git a/test/gstreamer/gstreamer_single_stream_test.cpp b/test/gstreamer/gstreamer_single_stream_test.cpp > > > >> new file mode 100644 > > > >> index 00000000..c19da3f2 > > > >> --- /dev/null > > > >> +++ b/test/gstreamer/gstreamer_single_stream_test.cpp > > > >> @@ -0,0 +1,116 @@ This file needs an SPDX header and a comment block like the other tests. > > > >> +#include <gst/gst.h> > > > >> +#include <iostream> > > > >> + > > > >> +#include "test.h" > > > >> + > > > >> +using namespace std; > > > >> + > > > >> +class GstreamerSingleStreamTest : public Test > > > >> +{ > > > >> +protected: > > > >> + int init() override > > > >> + { > > > >> + /* Initialize GStreamer */ > > > >> + GError *err_init = nullptr; > > > >> + if (!gst_init_check(nullptr, nullptr, &err_init)) { > > > >> + g_printerr("Could not initialize GStreamer: %s\n", > > > >> + err_init ? err_init->message : "unknown error"); > > > >> + if (err_init) > > > >> + g_error_free(err_init); > > > >> + > > > >> + return TestFail; > > > >> + } > > > >> + > > > >> + /* Create the elements */ > > > >> + libcamera_src_ = gst_element_factory_make("libcamerasrc", "libcamera"); > > > >> + convert0_ = gst_element_factory_make("videoconvert", "convert0"); > > > >> + sink0_ = gst_element_factory_make("autovideosink", "sink0"); > > > >> + > > > >> + /* Create the empty pipeline_ */ > > > >> + pipeline_ = gst_pipeline_new("test-pipeline"); > > > >> + > > > >> + if (!pipeline_ || !convert0_ || !sink0_ || !libcamera_src_) { > > > >> + g_printerr("Not all elements could be created.\n"); > > > >> + return TestFail; > > > >> + } > > > >> + > > > >> + return TestPass; > > > >> + } > > > >> + > > > >> + void cleanup() override > > > >> + { > > > >> + gst_message_unref(msg_); > > > >> + gst_object_unref(bus_); > > > >> + gst_element_set_state(pipeline_, GST_STATE_NULL); > > > >> + gst_object_unref(pipeline_); > > > >> + } > > > >> + > > > >> + int run() override > > > >> + { > > > >> + /* Build the pipeline */ > > > >> + gst_bin_add_many(GST_BIN(pipeline_), libcamera_src_, convert0_, sink0_, NULL); > > > >> + if (gst_element_link_many(libcamera_src_, convert0_, sink0_, NULL) != TRUE) { > > > >> + g_printerr("Elements could not be linked.\n"); > > > >> + gst_object_unref(pipeline_); > > > >> + return TestFail; > > > >> + } > > > >> + > > > >> + /* Start playing */ > > > >> + ret_ = gst_element_set_state(pipeline_, GST_STATE_PLAYING); > > > >> + if (ret_ == GST_STATE_CHANGE_FAILURE) { > > > >> + g_printerr("Unable to set the pipeline to the playing state.\n"); > > > >> + gst_object_unref(pipeline_); > > > >> + return TestFail; > > > >> + } > > > >> + > > > >> + /* Wait until error or EOS or timeout after 2 seconds*/ Missing space before */ > > > >> + GstClockTime timeout = 2000000000; > > > >> + bus_ = gst_element_get_bus(pipeline_); > > > >> + msg_ = gst_bus_timed_pop_filtered(bus_, timeout, > > > >> + > > GstMessageType((uint)GST_MESSAGE_ERROR | (uint)GST_MESSAGE_EOS)); > > > >> + > > > >> + /* Parse error message */ > > > >> + if (msg_ == NULL) > > > >> + return TestPass; > > > >> + > > > >> + switch (GST_MESSAGE_TYPE(msg_)) { > > > >> + case GST_MESSAGE_ERROR: > > > >> + GstreamerPrintError(msg_); > > > >> + return TestFail; > > > >> + break; > > > >> + case GST_MESSAGE_EOS: > > > >> + g_print("End-Of-Stream reached.\n"); > > > >> + return TestFail; > > > >> + break; > > > >> + default: > > > >> + g_printerr("Unexpected message received.\n"); > > > >> + return TestFail; > > > >> + break; > > > >> + } > > > >> + > > > >> + return TestPass; > > > >> + } > > > >> + > > > >> +private: > > > >> + GstElement *pipeline_, *libcamera_src_, *convert0_, *sink0_; > > > >> + GstBus *bus_; > > > >> + GstMessage *msg_; > > > >> + GstStateChangeReturn ret_; > > > >> + > > > >> + void GstreamerPrintError(GstMessage *msg) Functions start with a lowercase letter in the libcamera coding style. > > > >> + { > > > >> + GError *err; > > > >> + gchar *debug_info; > > > >> + > > > >> + gst_message_parse_error(msg, &err, &debug_info); > > > >> + g_printerr("Error received from element %s: %s\n", > > > >> + GST_OBJECT_NAME(msg->src), err->message); > > > >> + g_printerr("Debugging information: %s\n", > > > >> + debug_info ? debug_info : "none"); > > > >> + g_clear_error(&err); > > > >> + g_free(debug_info); > > > >> + } > > > >> +}; > > > >> + > > > >> +TEST_REGISTER(GstreamerSingleStreamTest) > > > >> + Extra blank line. > > > >> diff --git a/test/gstreamer/meson.build b/test/gstreamer/meson.build > > > >> new file mode 100644 > > > >> index 00000000..b99aa0da > > > >> --- /dev/null > > > >> +++ b/test/gstreamer/meson.build > > > >> @@ -0,0 +1,19 @@ > > > >> +# SPDX-License-Identifier: CC0-1.0 > > > >> + > > > >> +if not gst_enabled > > > >> + subdir_done() > > > >> +endif > > > >> + > > > >> +gstreamer_tests = [ > > > >> + ['single_stream_test', 'gstreamer_single_stream_test.cpp'], > > > >> +] > > > >> +gstreamer_dep = dependency('gstreamer-1.0', required: true) > > > >> + > > > >> +foreach t : gstreamer_tests > > > >> + exe = executable(t[0], t[1], > > > >> + dependencies : [libcamera_private, gstreamer_dep], > > > >> + link_with : test_libraries, > > > >> + include_directories : test_includes_internal) > > > >> + > > > >> + test(t[0], exe, suite : 'gstreamer', is_parallel : false) > > > >> +endforeach > > > >> diff --git a/test/meson.build b/test/meson.build > > > >> index 3bceb5df..d0466f17 100644 > > > >> --- a/test/meson.build > > > >> +++ b/test/meson.build > > > >> @@ -11,6 +11,7 @@ subdir('libtest') > > > >> > > > >> subdir('camera') > > > >> subdir('controls') > > > >> +subdir('gstreamer') > > > >> subdir('ipa') > > > >> subdir('ipc') > > > >> subdir('log')
Hi Laurent, I'll make the changes in v7. Regards, Vedant Paranjape On Wed, Aug 11, 2021 at 7:34 PM Laurent Pinchart < laurent.pinchart@ideasonboard.com> wrote: > Hi Vedant, > > On Wed, Aug 11, 2021 at 07:13:40PM +0530, Vedant Paranjape wrote: > > On Wed, Aug 11, 2021 at 6:34 PM Laurent Pinchart wrote: > > > On Wed, Aug 11, 2021 at 01:56:08PM +0100, Kieran Bingham wrote: > > > > On 11/08/2021 13:47, Kieran Bingham wrote: > > > > > On 11/08/2021 08:03, Vedant Paranjape wrote: > > > > >> This patch adds a test to test if single stream using > > > > >> libcamera's gstreamer element works. > > > > >> > > > > >> Signed-off-by: Vedant Paranjape <vedantparanjape160201@gmail.com> > > > > >> Reviewed-by: Paul Elder <paul.elder@ideasonboard.com> > > > > > > > > > > Is there anything specific needed to run this? > > > > > > > > > > When I ran it here I get: > > > > > > > > > > > > > > > 12/66 libcamera:gstreamer / single_stream_test > > > > > FAIL 0.01s (exit status 255 or signal 127 SIGinvalid) > > > > > stderr: > > > > > Not all elements could be created. > > > > > > > > Somehow we need to export the GST_PLUGIN_PATH from the build to the > test > > > > when it is run. > > > > > > I've run into the same issue. This needs to be fixed, as otherwise > > > running 'ninja test' will fail. > > > > I think you need to set the path or install libcamera in root, not sure > > what needs to be fixed. > > That's the whole point, it has to run without installing, and without > setting an environment variable. The following has to work without any > test failure: > > git clone https://git.libcamera.org/libcamera/libcamera.git/ > cd libcamera > mkdir build > cd build > meson setup .. > ninja > ninja test > > One option is to set the environment variable (or use a corresponding > GStreamer C API, which would be better) from within the test. > > > > Manually running the test, while manually setting the path gives: > > > > > > > > GST_PLUGIN_PATH=./build/src/gstreamer/ > ./build/test/gstreamer/single_stream_test > > > > > [322:51:39.768296143] [2459570] INFO IPAManager > ipa_manager.cpp:138 libcamera is not installed. Adding > '/home/kbingham/iob/libcamera/chromeos/src/third_party/libcamera/build/src/ipa' > to the IPA search path > > > > > [322:51:39.769209245] [2459570] INFO Camera > camera_manager.cpp:294 libcamera v0.0.0+2918-15014c37 > > > > > [322:51:39.772516638] [2459575] INFO V4L2 v4l2_subdevice.cpp:242 > 'Sensor B': Using /dev/v4l-subdev1 > > > > > [322:51:39.773277255] [2459575] WARN CameraSensorProperties > camera_sensor_properties.cpp:123 No static properties available for 'Sensor > B' > > > > > [322:51:39.773290289] [2459575] WARN CameraSensorProperties > camera_sensor_properties.cpp:125 Please consider updating the camera sensor > properties database > > > > > [322:51:39.773298484] [2459575] WARN CameraSensor > camera_sensor.cpp:403 'Sensor B': Failed to retrieve the camera location > > > > > [322:51:39.773317911] [2459575] INFO V4L2 v4l2_subdevice.cpp:242 > 'Debayer B': Using /dev/v4l-subdev3 > > > > > [322:51:39.773365811] [2459575] INFO V4L2 v4l2_subdevice.cpp:242 > 'Scaler': Using /dev/v4l-subdev5 > > > > > [322:51:39.773441643] [2459575] WARN IPAManager > ipa_manager.cpp:280 IPA module > /home/kbingham/iob/libcamera/chromeos/src/third_party/libcamera/build/src/ipa/vimc/ipa_vimc.so > signature regarded as valid > > > > > [322:51:39.773731977] [2459575] INFO IPAProxy ipa_proxy.cpp:130 > libcamera is not installed. Loading IPA configuration from > '/home/kbingham/iob/libcamera/chromeos/src/third_party/libcamera/src/ipa/vimc/data' > > > > > [322:51:39.838754646] [2459576] INFO Camera camera.cpp:873 > configuring streams: (0) 156x120-BGR888 > > > > > > > > > > (single_stream_test:2459570): GStreamer-CRITICAL **: 13:51:14.445: > gst_mini_object_unref: assertion 'mini_object != NULL' failed > > Additionally, it would be nice if the test returned an error gracefully > in this case, instead of crashing with a failed assertion. Error > handling is important. > > > > > But even that only showed me a black box that appeared, and then > seemed > > > > to disappear again. > > > > > > > > We might also want to run the automated tests on systems without a > > > > display, so pop windows might not work there. > > > > > > > > But I'd be tempted to say we can deal with that when we find an > actual > > > > need for that, and keep the visual test, as ... (if It works, and > shows > > > > an image) it would be a nice visual confirmation while running the > tests. > > > > > > > > Otherwise, perhaps a pipeline that generates an output PNG or encoded > > > > video might be required, or even just a null sink if that's possible? > > > > > > A null sink would be better, as I already run tests on headless > systems. > > > It may be as simple as s/autovideosink/fakevideosink/ in the code > below, > > > so I think we should already address that. > > > > I tried this, it works, should I sent a new patch with this ? > > Yes, please do this in v6. > > While at it, could you please run the test under valgrind, to ensure > there's no memory leak (at least no memory leak caused by the test, > leaks in third party libraries themselves, such as libudev, are not our > fault). > > > > But that can be later anyway. > > > > > > > >> --- > > > > >> .../gstreamer_single_stream_test.cpp | 116 > ++++++++++++++++++ > > > > >> test/gstreamer/meson.build | 19 +++ > > > > >> test/meson.build | 1 + > > > > >> 3 files changed, 136 insertions(+) > > > > >> create mode 100644 > test/gstreamer/gstreamer_single_stream_test.cpp > > > > >> create mode 100644 test/gstreamer/meson.build > > > > >> > > > > >> diff --git a/test/gstreamer/gstreamer_single_stream_test.cpp > b/test/gstreamer/gstreamer_single_stream_test.cpp > > > > >> new file mode 100644 > > > > >> index 00000000..c19da3f2 > > > > >> --- /dev/null > > > > >> +++ b/test/gstreamer/gstreamer_single_stream_test.cpp > > > > >> @@ -0,0 +1,116 @@ > > This file needs an SPDX header and a comment block like the other tests. > > > > > >> +#include <gst/gst.h> > > > > >> +#include <iostream> > > > > >> + > > > > >> +#include "test.h" > > > > >> + > > > > >> +using namespace std; > > > > >> + > > > > >> +class GstreamerSingleStreamTest : public Test > > > > >> +{ > > > > >> +protected: > > > > >> + int init() override > > > > >> + { > > > > >> + /* Initialize GStreamer */ > > > > >> + GError *err_init = nullptr; > > > > >> + if (!gst_init_check(nullptr, nullptr, &err_init)) { > > > > >> + g_printerr("Could not initialize GStreamer: > %s\n", > > > > >> + err_init ? err_init->message : > "unknown error"); > > > > >> + if (err_init) > > > > >> + g_error_free(err_init); > > > > >> + > > > > >> + return TestFail; > > > > >> + } > > > > >> + > > > > >> + /* Create the elements */ > > > > >> + libcamera_src_ = > gst_element_factory_make("libcamerasrc", "libcamera"); > > > > >> + convert0_ = gst_element_factory_make("videoconvert", > "convert0"); > > > > >> + sink0_ = gst_element_factory_make("autovideosink", > "sink0"); > > > > >> + > > > > >> + /* Create the empty pipeline_ */ > > > > >> + pipeline_ = gst_pipeline_new("test-pipeline"); > > > > >> + > > > > >> + if (!pipeline_ || !convert0_ || !sink0_ || > !libcamera_src_) { > > > > >> + g_printerr("Not all elements could be > created.\n"); > > > > >> + return TestFail; > > > > >> + } > > > > >> + > > > > >> + return TestPass; > > > > >> + } > > > > >> + > > > > >> + void cleanup() override > > > > >> + { > > > > >> + gst_message_unref(msg_); > > > > >> + gst_object_unref(bus_); > > > > >> + gst_element_set_state(pipeline_, GST_STATE_NULL); > > > > >> + gst_object_unref(pipeline_); > > > > >> + } > > > > >> + > > > > >> + int run() override > > > > >> + { > > > > >> + /* Build the pipeline */ > > > > >> + gst_bin_add_many(GST_BIN(pipeline_), libcamera_src_, > convert0_, sink0_, NULL); > > > > >> + if (gst_element_link_many(libcamera_src_, convert0_, > sink0_, NULL) != TRUE) { > > > > >> + g_printerr("Elements could not be linked.\n"); > > > > >> + gst_object_unref(pipeline_); > > > > >> + return TestFail; > > > > >> + } > > > > >> + > > > > >> + /* Start playing */ > > > > >> + ret_ = gst_element_set_state(pipeline_, > GST_STATE_PLAYING); > > > > >> + if (ret_ == GST_STATE_CHANGE_FAILURE) { > > > > >> + g_printerr("Unable to set the pipeline to the > playing state.\n"); > > > > >> + gst_object_unref(pipeline_); > > > > >> + return TestFail; > > > > >> + } > > > > >> + > > > > >> + /* Wait until error or EOS or timeout after 2 seconds*/ > > Missing space before */ > > > > > >> + GstClockTime timeout = 2000000000; > > > > >> + bus_ = gst_element_get_bus(pipeline_); > > > > >> + msg_ = gst_bus_timed_pop_filtered(bus_, timeout, > > > > >> + > > > GstMessageType((uint)GST_MESSAGE_ERROR | (uint)GST_MESSAGE_EOS)); > > > > >> + > > > > >> + /* Parse error message */ > > > > >> + if (msg_ == NULL) > > > > >> + return TestPass; > > > > >> + > > > > >> + switch (GST_MESSAGE_TYPE(msg_)) { > > > > >> + case GST_MESSAGE_ERROR: > > > > >> + GstreamerPrintError(msg_); > > > > >> + return TestFail; > > > > >> + break; > > > > >> + case GST_MESSAGE_EOS: > > > > >> + g_print("End-Of-Stream reached.\n"); > > > > >> + return TestFail; > > > > >> + break; > > > > >> + default: > > > > >> + g_printerr("Unexpected message received.\n"); > > > > >> + return TestFail; > > > > >> + break; > > > > >> + } > > > > >> + > > > > >> + return TestPass; > > > > >> + } > > > > >> + > > > > >> +private: > > > > >> + GstElement *pipeline_, *libcamera_src_, *convert0_, *sink0_; > > > > >> + GstBus *bus_; > > > > >> + GstMessage *msg_; > > > > >> + GstStateChangeReturn ret_; > > > > >> + > > > > >> + void GstreamerPrintError(GstMessage *msg) > > Functions start with a lowercase letter in the libcamera coding style. > > > > > >> + { > > > > >> + GError *err; > > > > >> + gchar *debug_info; > > > > >> + > > > > >> + gst_message_parse_error(msg, &err, &debug_info); > > > > >> + g_printerr("Error received from element %s: %s\n", > > > > >> + GST_OBJECT_NAME(msg->src), err->message); > > > > >> + g_printerr("Debugging information: %s\n", > > > > >> + debug_info ? debug_info : "none"); > > > > >> + g_clear_error(&err); > > > > >> + g_free(debug_info); > > > > >> + } > > > > >> +}; > > > > >> + > > > > >> +TEST_REGISTER(GstreamerSingleStreamTest) > > > > >> + > > Extra blank line. > > > > > >> diff --git a/test/gstreamer/meson.build > b/test/gstreamer/meson.build > > > > >> new file mode 100644 > > > > >> index 00000000..b99aa0da > > > > >> --- /dev/null > > > > >> +++ b/test/gstreamer/meson.build > > > > >> @@ -0,0 +1,19 @@ > > > > >> +# SPDX-License-Identifier: CC0-1.0 > > > > >> + > > > > >> +if not gst_enabled > > > > >> + subdir_done() > > > > >> +endif > > > > >> + > > > > >> +gstreamer_tests = [ > > > > >> + ['single_stream_test', 'gstreamer_single_stream_test.cpp'], > > > > >> +] > > > > >> +gstreamer_dep = dependency('gstreamer-1.0', required: true) > > > > >> + > > > > >> +foreach t : gstreamer_tests > > > > >> + exe = executable(t[0], t[1], > > > > >> + dependencies : [libcamera_private, > gstreamer_dep], > > > > >> + link_with : test_libraries, > > > > >> + include_directories : > test_includes_internal) > > > > >> + > > > > >> + test(t[0], exe, suite : 'gstreamer', is_parallel : false) > > > > >> +endforeach > > > > >> diff --git a/test/meson.build b/test/meson.build > > > > >> index 3bceb5df..d0466f17 100644 > > > > >> --- a/test/meson.build > > > > >> +++ b/test/meson.build > > > > >> @@ -11,6 +11,7 @@ subdir('libtest') > > > > >> > > > > >> subdir('camera') > > > > >> subdir('controls') > > > > >> +subdir('gstreamer') > > > > >> subdir('ipa') > > > > >> subdir('ipc') > > > > >> subdir('log') > > -- > Regards, > > Laurent Pinchart >
Hi Laurent, On Wed, Aug 11, 2021 at 7:34 PM Laurent Pinchart < laurent.pinchart@ideasonboard.com> wrote: > Hi Vedant, > > On Wed, Aug 11, 2021 at 07:13:40PM +0530, Vedant Paranjape wrote: > > On Wed, Aug 11, 2021 at 6:34 PM Laurent Pinchart wrote: > > > On Wed, Aug 11, 2021 at 01:56:08PM +0100, Kieran Bingham wrote: > > > > On 11/08/2021 13:47, Kieran Bingham wrote: > > > > > On 11/08/2021 08:03, Vedant Paranjape wrote: > > > > >> This patch adds a test to test if single stream using > > > > >> libcamera's gstreamer element works. > > > > >> > > > > >> Signed-off-by: Vedant Paranjape <vedantparanjape160201@gmail.com> > > > > >> Reviewed-by: Paul Elder <paul.elder@ideasonboard.com> > > > > > > > > > > Is there anything specific needed to run this? > > > > > > > > > > When I ran it here I get: > > > > > > > > > > > > > > > 12/66 libcamera:gstreamer / single_stream_test > > > > > FAIL 0.01s (exit status 255 or signal 127 SIGinvalid) > > > > > stderr: > > > > > Not all elements could be created. > > > > > > > > Somehow we need to export the GST_PLUGIN_PATH from the build to the > test > > > > when it is run. > > > > > > I've run into the same issue. This needs to be fixed, as otherwise > > > running 'ninja test' will fail. > > > > I think you need to set the path or install libcamera in root, not sure > > what needs to be fixed. > > That's the whole point, it has to run without installing, and without > setting an environment variable. The following has to work without any > test failure: > > git clone https://git.libcamera.org/libcamera/libcamera.git/ > cd libcamera > mkdir build > cd build > meson setup .. > ninja > ninja test > > One option is to set the environment variable (or use a corresponding > GStreamer C API, which would be better) from within the test. > > > > Manually running the test, while manually setting the path gives: > > > > > > > > GST_PLUGIN_PATH=./build/src/gstreamer/ > ./build/test/gstreamer/single_stream_test > > > > > [322:51:39.768296143] [2459570] INFO IPAManager > ipa_manager.cpp:138 libcamera is not installed. Adding > '/home/kbingham/iob/libcamera/chromeos/src/third_party/libcamera/build/src/ipa' > to the IPA search path > > > > > [322:51:39.769209245] [2459570] INFO Camera > camera_manager.cpp:294 libcamera v0.0.0+2918-15014c37 > > > > > [322:51:39.772516638] [2459575] INFO V4L2 v4l2_subdevice.cpp:242 > 'Sensor B': Using /dev/v4l-subdev1 > > > > > [322:51:39.773277255] [2459575] WARN CameraSensorProperties > camera_sensor_properties.cpp:123 No static properties available for 'Sensor > B' > > > > > [322:51:39.773290289] [2459575] WARN CameraSensorProperties > camera_sensor_properties.cpp:125 Please consider updating the camera sensor > properties database > > > > > [322:51:39.773298484] [2459575] WARN CameraSensor > camera_sensor.cpp:403 'Sensor B': Failed to retrieve the camera location > > > > > [322:51:39.773317911] [2459575] INFO V4L2 v4l2_subdevice.cpp:242 > 'Debayer B': Using /dev/v4l-subdev3 > > > > > [322:51:39.773365811] [2459575] INFO V4L2 v4l2_subdevice.cpp:242 > 'Scaler': Using /dev/v4l-subdev5 > > > > > [322:51:39.773441643] [2459575] WARN IPAManager > ipa_manager.cpp:280 IPA module > /home/kbingham/iob/libcamera/chromeos/src/third_party/libcamera/build/src/ipa/vimc/ipa_vimc.so > signature regarded as valid > > > > > [322:51:39.773731977] [2459575] INFO IPAProxy ipa_proxy.cpp:130 > libcamera is not installed. Loading IPA configuration from > '/home/kbingham/iob/libcamera/chromeos/src/third_party/libcamera/src/ipa/vimc/data' > > > > > [322:51:39.838754646] [2459576] INFO Camera camera.cpp:873 > configuring streams: (0) 156x120-BGR888 > > > > > > > > > > (single_stream_test:2459570): GStreamer-CRITICAL **: 13:51:14.445: > gst_mini_object_unref: assertion 'mini_object != NULL' failed > > Additionally, it would be nice if the test returned an error gracefully > in this case, instead of crashing with a failed assertion. Error > handling is important. > This happened as I unref msg_ in cleanup, it should have been in run() itself, according to this answer: https://stackoverflow.com/a/63724345. I am trying to unref the object which is not owned by cleanup() maybe. Moving it to run() fixed the error. > > > But even that only showed me a black box that appeared, and then > seemed > > > > to disappear again. > > > > > > > > We might also want to run the automated tests on systems without a > > > > display, so pop windows might not work there. > > > > > > > > But I'd be tempted to say we can deal with that when we find an > actual > > > > need for that, and keep the visual test, as ... (if It works, and > shows > > > > an image) it would be a nice visual confirmation while running the > tests. > > > > > > > > Otherwise, perhaps a pipeline that generates an output PNG or encoded > > > > video might be required, or even just a null sink if that's possible? > > > > > > A null sink would be better, as I already run tests on headless > systems. > > > It may be as simple as s/autovideosink/fakevideosink/ in the code > below, > > > so I think we should already address that. > > > > I tried this, it works, should I sent a new patch with this ? > > Yes, please do this in v6. > > While at it, could you please run the test under valgrind, to ensure > there's no memory leak (at least no memory leak caused by the test, > leaks in third party libraries themselves, such as libudev, are not our > fault). > > > > But that can be later anyway. > > > > > > > >> --- > > > > >> .../gstreamer_single_stream_test.cpp | 116 > ++++++++++++++++++ > > > > >> test/gstreamer/meson.build | 19 +++ > > > > >> test/meson.build | 1 + > > > > >> 3 files changed, 136 insertions(+) > > > > >> create mode 100644 > test/gstreamer/gstreamer_single_stream_test.cpp > > > > >> create mode 100644 test/gstreamer/meson.build > > > > >> > > > > >> diff --git a/test/gstreamer/gstreamer_single_stream_test.cpp > b/test/gstreamer/gstreamer_single_stream_test.cpp > > > > >> new file mode 100644 > > > > >> index 00000000..c19da3f2 > > > > >> --- /dev/null > > > > >> +++ b/test/gstreamer/gstreamer_single_stream_test.cpp > > > > >> @@ -0,0 +1,116 @@ > > This file needs an SPDX header and a comment block like the other tests. > > > > > >> +#include <gst/gst.h> > > > > >> +#include <iostream> > > > > >> + > > > > >> +#include "test.h" > > > > >> + > > > > >> +using namespace std; > > > > >> + > > > > >> +class GstreamerSingleStreamTest : public Test > > > > >> +{ > > > > >> +protected: > > > > >> + int init() override > > > > >> + { > > > > >> + /* Initialize GStreamer */ > > > > >> + GError *err_init = nullptr; > > > > >> + if (!gst_init_check(nullptr, nullptr, &err_init)) { > > > > >> + g_printerr("Could not initialize GStreamer: > %s\n", > > > > >> + err_init ? err_init->message : > "unknown error"); > > > > >> + if (err_init) > > > > >> + g_error_free(err_init); > > > > >> + > > > > >> + return TestFail; > > > > >> + } > > > > >> + > > > > >> + /* Create the elements */ > > > > >> + libcamera_src_ = > gst_element_factory_make("libcamerasrc", "libcamera"); > > > > >> + convert0_ = gst_element_factory_make("videoconvert", > "convert0"); > > > > >> + sink0_ = gst_element_factory_make("autovideosink", > "sink0"); > > > > >> + > > > > >> + /* Create the empty pipeline_ */ > > > > >> + pipeline_ = gst_pipeline_new("test-pipeline"); > > > > >> + > > > > >> + if (!pipeline_ || !convert0_ || !sink0_ || > !libcamera_src_) { > > > > >> + g_printerr("Not all elements could be > created.\n"); > > > > >> + return TestFail; > > > > >> + } > > > > >> + > > > > >> + return TestPass; > > > > >> + } > > > > >> + > > > > >> + void cleanup() override > > > > >> + { > > > > >> + gst_message_unref(msg_); > > > > >> + gst_object_unref(bus_); > > > > >> + gst_element_set_state(pipeline_, GST_STATE_NULL); > > > > >> + gst_object_unref(pipeline_); > > > > >> + } > > > > >> + > > > > >> + int run() override > > > > >> + { > > > > >> + /* Build the pipeline */ > > > > >> + gst_bin_add_many(GST_BIN(pipeline_), libcamera_src_, > convert0_, sink0_, NULL); > > > > >> + if (gst_element_link_many(libcamera_src_, convert0_, > sink0_, NULL) != TRUE) { > > > > >> + g_printerr("Elements could not be linked.\n"); > > > > >> + gst_object_unref(pipeline_); > > > > >> + return TestFail; > > > > >> + } > > > > >> + > > > > >> + /* Start playing */ > > > > >> + ret_ = gst_element_set_state(pipeline_, > GST_STATE_PLAYING); > > > > >> + if (ret_ == GST_STATE_CHANGE_FAILURE) { > > > > >> + g_printerr("Unable to set the pipeline to the > playing state.\n"); > > > > >> + gst_object_unref(pipeline_); > > > > >> + return TestFail; > > > > >> + } > > > > >> + > > > > >> + /* Wait until error or EOS or timeout after 2 seconds*/ > > Missing space before */ > > > > > >> + GstClockTime timeout = 2000000000; > > > > >> + bus_ = gst_element_get_bus(pipeline_); > > > > >> + msg_ = gst_bus_timed_pop_filtered(bus_, timeout, > > > > >> + > > > GstMessageType((uint)GST_MESSAGE_ERROR | (uint)GST_MESSAGE_EOS)); > > > > >> + > > > > >> + /* Parse error message */ > > > > >> + if (msg_ == NULL) > > > > >> + return TestPass; > > > > >> + > > > > >> + switch (GST_MESSAGE_TYPE(msg_)) { > > > > >> + case GST_MESSAGE_ERROR: > > > > >> + GstreamerPrintError(msg_); > > > > >> + return TestFail; > > > > >> + break; > > > > >> + case GST_MESSAGE_EOS: > > > > >> + g_print("End-Of-Stream reached.\n"); > > > > >> + return TestFail; > > > > >> + break; > > > > >> + default: > > > > >> + g_printerr("Unexpected message received.\n"); > > > > >> + return TestFail; > > > > >> + break; > > > > >> + } > > > > >> + > > > > >> + return TestPass; > > > > >> + } > > > > >> + > > > > >> +private: > > > > >> + GstElement *pipeline_, *libcamera_src_, *convert0_, *sink0_; > > > > >> + GstBus *bus_; > > > > >> + GstMessage *msg_; > > > > >> + GstStateChangeReturn ret_; > > > > >> + > > > > >> + void GstreamerPrintError(GstMessage *msg) > > Functions start with a lowercase letter in the libcamera coding style. > > > > > >> + { > > > > >> + GError *err; > > > > >> + gchar *debug_info; > > > > >> + > > > > >> + gst_message_parse_error(msg, &err, &debug_info); > > > > >> + g_printerr("Error received from element %s: %s\n", > > > > >> + GST_OBJECT_NAME(msg->src), err->message); > > > > >> + g_printerr("Debugging information: %s\n", > > > > >> + debug_info ? debug_info : "none"); > > > > >> + g_clear_error(&err); > > > > >> + g_free(debug_info); > > > > >> + } > > > > >> +}; > > > > >> + > > > > >> +TEST_REGISTER(GstreamerSingleStreamTest) > > > > >> + > > Extra blank line. > > > > > >> diff --git a/test/gstreamer/meson.build > b/test/gstreamer/meson.build > > > > >> new file mode 100644 > > > > >> index 00000000..b99aa0da > > > > >> --- /dev/null > > > > >> +++ b/test/gstreamer/meson.build > > > > >> @@ -0,0 +1,19 @@ > > > > >> +# SPDX-License-Identifier: CC0-1.0 > > > > >> + > > > > >> +if not gst_enabled > > > > >> + subdir_done() > > > > >> +endif > > > > >> + > > > > >> +gstreamer_tests = [ > > > > >> + ['single_stream_test', 'gstreamer_single_stream_test.cpp'], > > > > >> +] > > > > >> +gstreamer_dep = dependency('gstreamer-1.0', required: true) > > > > >> + > > > > >> +foreach t : gstreamer_tests > > > > >> + exe = executable(t[0], t[1], > > > > >> + dependencies : [libcamera_private, > gstreamer_dep], > > > > >> + link_with : test_libraries, > > > > >> + include_directories : > test_includes_internal) > > > > >> + > > > > >> + test(t[0], exe, suite : 'gstreamer', is_parallel : false) > > > > >> +endforeach > > > > >> diff --git a/test/meson.build b/test/meson.build > > > > >> index 3bceb5df..d0466f17 100644 > > > > >> --- a/test/meson.build > > > > >> +++ b/test/meson.build > > > > >> @@ -11,6 +11,7 @@ subdir('libtest') > > > > >> > > > > >> subdir('camera') > > > > >> subdir('controls') > > > > >> +subdir('gstreamer') > > > > >> subdir('ipa') > > > > >> subdir('ipc') > > > > >> subdir('log') > > -- > Regards, > > Laurent Pinchart >
diff --git a/test/gstreamer/gstreamer_single_stream_test.cpp b/test/gstreamer/gstreamer_single_stream_test.cpp new file mode 100644 index 00000000..c19da3f2 --- /dev/null +++ b/test/gstreamer/gstreamer_single_stream_test.cpp @@ -0,0 +1,116 @@ +#include <gst/gst.h> +#include <iostream> + +#include "test.h" + +using namespace std; + +class GstreamerSingleStreamTest : public Test +{ +protected: + int init() override + { + /* Initialize GStreamer */ + GError *err_init = nullptr; + if (!gst_init_check(nullptr, nullptr, &err_init)) { + g_printerr("Could not initialize GStreamer: %s\n", + err_init ? err_init->message : "unknown error"); + if (err_init) + g_error_free(err_init); + + return TestFail; + } + + /* Create the elements */ + libcamera_src_ = gst_element_factory_make("libcamerasrc", "libcamera"); + convert0_ = gst_element_factory_make("videoconvert", "convert0"); + sink0_ = gst_element_factory_make("autovideosink", "sink0"); + + /* Create the empty pipeline_ */ + pipeline_ = gst_pipeline_new("test-pipeline"); + + if (!pipeline_ || !convert0_ || !sink0_ || !libcamera_src_) { + g_printerr("Not all elements could be created.\n"); + return TestFail; + } + + return TestPass; + } + + void cleanup() override + { + gst_message_unref(msg_); + gst_object_unref(bus_); + gst_element_set_state(pipeline_, GST_STATE_NULL); + gst_object_unref(pipeline_); + } + + int run() override + { + /* Build the pipeline */ + gst_bin_add_many(GST_BIN(pipeline_), libcamera_src_, convert0_, sink0_, NULL); + if (gst_element_link_many(libcamera_src_, convert0_, sink0_, NULL) != TRUE) { + g_printerr("Elements could not be linked.\n"); + gst_object_unref(pipeline_); + return TestFail; + } + + /* Start playing */ + ret_ = gst_element_set_state(pipeline_, GST_STATE_PLAYING); + if (ret_ == GST_STATE_CHANGE_FAILURE) { + g_printerr("Unable to set the pipeline to the playing state.\n"); + gst_object_unref(pipeline_); + return TestFail; + } + + /* Wait until error or EOS or timeout after 2 seconds*/ + GstClockTime timeout = 2000000000; + bus_ = gst_element_get_bus(pipeline_); + msg_ = gst_bus_timed_pop_filtered(bus_, timeout, + GstMessageType((uint)GST_MESSAGE_ERROR | (uint)GST_MESSAGE_EOS)); + + /* Parse error message */ + if (msg_ == NULL) + return TestPass; + + switch (GST_MESSAGE_TYPE(msg_)) { + case GST_MESSAGE_ERROR: + GstreamerPrintError(msg_); + return TestFail; + break; + case GST_MESSAGE_EOS: + g_print("End-Of-Stream reached.\n"); + return TestFail; + break; + default: + g_printerr("Unexpected message received.\n"); + return TestFail; + break; + } + + return TestPass; + } + +private: + GstElement *pipeline_, *libcamera_src_, *convert0_, *sink0_; + GstBus *bus_; + GstMessage *msg_; + GstStateChangeReturn ret_; + + void GstreamerPrintError(GstMessage *msg) + { + GError *err; + gchar *debug_info; + + gst_message_parse_error(msg, &err, &debug_info); + g_printerr("Error received from element %s: %s\n", + GST_OBJECT_NAME(msg->src), err->message); + g_printerr("Debugging information: %s\n", + debug_info ? debug_info : "none"); + g_clear_error(&err); + g_free(debug_info); + } +}; + +TEST_REGISTER(GstreamerSingleStreamTest) + diff --git a/test/gstreamer/meson.build b/test/gstreamer/meson.build new file mode 100644 index 00000000..b99aa0da --- /dev/null +++ b/test/gstreamer/meson.build @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: CC0-1.0 + +if not gst_enabled + subdir_done() +endif + +gstreamer_tests = [ + ['single_stream_test', 'gstreamer_single_stream_test.cpp'], +] +gstreamer_dep = dependency('gstreamer-1.0', required: true) + +foreach t : gstreamer_tests + exe = executable(t[0], t[1], + dependencies : [libcamera_private, gstreamer_dep], + link_with : test_libraries, + include_directories : test_includes_internal) + + test(t[0], exe, suite : 'gstreamer', is_parallel : false) +endforeach diff --git a/test/meson.build b/test/meson.build index 3bceb5df..d0466f17 100644 --- a/test/meson.build +++ b/test/meson.build @@ -11,6 +11,7 @@ subdir('libtest') subdir('camera') subdir('controls') +subdir('gstreamer') subdir('ipa') subdir('ipc') subdir('log')