Message ID | 20210924083821.1877829-1-vedantparanjape160201@gmail.com |
---|---|
State | Accepted |
Headers | show |
Series |
|
Related | show |
Hi Vedant, On Fri, Sep 24, 2021 at 02:08:21PM +0530, Vedant Paranjape wrote: > This patch adds a test to test if multi stream using libcamera's > gstreamer element works. > > Test will run only on devices that support multistream capture, eg., > devices that use IPU3 and raspberrypi pipeline. This was tested on > a Raspberry Pi 4B+. > > Signed-off-by: Vedant Paranjape <vedantparanjape160201@gmail.com> > Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com> > --- > .../gstreamer/gstreamer_multi_stream_test.cpp | 124 ++++++++++++++++++ > test/gstreamer/meson.build | 1 + > 2 files changed, 125 insertions(+) > create mode 100644 test/gstreamer/gstreamer_multi_stream_test.cpp > > diff --git a/test/gstreamer/gstreamer_multi_stream_test.cpp b/test/gstreamer/gstreamer_multi_stream_test.cpp > new file mode 100644 > index 000000000000..6a9a6f2509cb > --- /dev/null > +++ b/test/gstreamer/gstreamer_multi_stream_test.cpp > @@ -0,0 +1,124 @@ > +/* SPDX-License-Identifier: GPL-2.0-or-later */ > +/* > + * Copyright (C) 2021, Vedant Paranjape > + * > + * gstreamer_multi_stream_test.cpp - GStreamer multi stream capture test > + */ > + > +#include <iostream> > +#include <unistd.h> > + > +#include <libcamera/libcamera.h> > + > +#include <gst/gst.h> > + > +#include "gstreamer_test.h" > +#include "test.h" Could you please later send a patch to remove the unnecessary includes from the single stream test? > + > +using namespace std; > + > +class GstreamerMultiStreamTest : public GstreamerTest, public Test > +{ > +public: > + GstreamerMultiStreamTest() > + : GstreamerTest() > + { > + } > + > +protected: > + int init() override > + { > + if (status_ != TestPass) > + return status_; > + > + /* Check if platform support multistream output */ s/support/supports/ s/output/capture/ I'll do these changes when applying. Looks good! Reviewed-by: Paul Elder <paul.elder@ideasonboard.com> > + libcamera::CameraManager cm; > + cm.start(); > + bool cameraFound = false; > + for (auto &camera : cm.cameras()) { > + if (camera->streams().size() > 1) { > + cameraName_ = camera->id(); > + cameraFound = true; > + cm.stop(); > + break; > + } > + } > + > + if (!cameraFound) { > + cm.stop(); > + return TestSkip; > + } > + > + const gchar *streamDescription = "queue ! fakesink"; > + g_autoptr(GError) error = NULL; > + > + stream0_ = gst_parse_bin_from_description_full(streamDescription, TRUE, > + NULL, > + GST_PARSE_FLAG_FATAL_ERRORS, > + &error); > + if (!stream0_) { > + g_printerr("Stream0 could not be created (%s)\n", error->message); > + return TestFail; > + } > + g_object_ref_sink(stream0_); > + > + stream1_ = gst_parse_bin_from_description_full(streamDescription, TRUE, > + NULL, > + GST_PARSE_FLAG_FATAL_ERRORS, > + &error); > + if (!stream1_) { > + g_printerr("Stream1 could not be created (%s)\n", error->message); > + return TestFail; > + } > + g_object_ref_sink(stream1_); > + > + if (createPipeline() != TestPass) > + return TestFail; > + > + return TestPass; > + } > + > + int run() override > + { > + g_object_set(libcameraSrc_, "camera-name", cameraName_.c_str(), NULL); > + > + /* Build the pipeline */ > + gst_bin_add_many(GST_BIN(pipeline_), libcameraSrc_, > + stream0_, stream1_, NULL); > + > + g_autoptr(GstPad) src_pad = gst_element_get_static_pad(libcameraSrc_, "src"); > + g_autoptr(GstPad) request_pad = gst_element_get_request_pad(libcameraSrc_, "src_%u"); > + > + { > + g_autoptr(GstPad) queue0_sink_pad = gst_element_get_static_pad(stream0_, "sink"); > + g_autoptr(GstPad) queue1_sink_pad = gst_element_get_static_pad(stream1_, "sink"); > + > + if (gst_pad_link(src_pad, queue0_sink_pad) != GST_PAD_LINK_OK || > + gst_pad_link(request_pad, queue1_sink_pad) != GST_PAD_LINK_OK) { > + g_printerr("Pads could not be linked.\n"); > + return TestFail; > + } > + } > + > + if (startPipeline() != TestPass) > + return TestFail; > + > + if (processEvent() != TestPass) > + return TestFail; > + > + return TestPass; > + } > + > + void cleanup() override > + { > + g_clear_object(&stream0_); > + g_clear_object(&stream1_); > + } > + > +private: > + std::string cameraName_; > + GstElement *stream0_; > + GstElement *stream1_; > +}; > + > +TEST_REGISTER(GstreamerMultiStreamTest) > diff --git a/test/gstreamer/meson.build b/test/gstreamer/meson.build > index aca53b920365..10058fc5206f 100644 > --- a/test/gstreamer/meson.build > +++ b/test/gstreamer/meson.build > @@ -6,6 +6,7 @@ endif > > gstreamer_tests = [ > ['single_stream_test', 'gstreamer_single_stream_test.cpp'], > + ['multi_stream_test', 'gstreamer_multi_stream_test.cpp'], > ] > gstreamer_dep = dependency('gstreamer-1.0', required: true) > > -- > 2.25.1 >
On Fri, Sep 24, 2021 at 2:21 PM <paul.elder@ideasonboard.com> wrote: > > Hi Vedant, > > On Fri, Sep 24, 2021 at 02:08:21PM +0530, Vedant Paranjape wrote: > > This patch adds a test to test if multi stream using libcamera's > > gstreamer element works. > > > > Test will run only on devices that support multistream capture, eg., > > devices that use IPU3 and raspberrypi pipeline. This was tested on > > a Raspberry Pi 4B+. > > > > Signed-off-by: Vedant Paranjape <vedantparanjape160201@gmail.com> > > Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com> > > --- > > .../gstreamer/gstreamer_multi_stream_test.cpp | 124 ++++++++++++++++++ > > test/gstreamer/meson.build | 1 + > > 2 files changed, 125 insertions(+) > > create mode 100644 test/gstreamer/gstreamer_multi_stream_test.cpp > > > > diff --git a/test/gstreamer/gstreamer_multi_stream_test.cpp b/test/gstreamer/gstreamer_multi_stream_test.cpp > > new file mode 100644 > > index 000000000000..6a9a6f2509cb > > --- /dev/null > > +++ b/test/gstreamer/gstreamer_multi_stream_test.cpp > > @@ -0,0 +1,124 @@ > > +/* SPDX-License-Identifier: GPL-2.0-or-later */ > > +/* > > + * Copyright (C) 2021, Vedant Paranjape > > + * > > + * gstreamer_multi_stream_test.cpp - GStreamer multi stream capture test > > + */ > > + > > +#include <iostream> > > +#include <unistd.h> > > + > > +#include <libcamera/libcamera.h> > > + > > +#include <gst/gst.h> > > + > > +#include "gstreamer_test.h" > > +#include "test.h" > > Could you please later send a patch to remove the unnecessary includes > from the single stream test? > Yes, I will send a patch. > > + > > +using namespace std; > > + > > +class GstreamerMultiStreamTest : public GstreamerTest, public Test > > +{ > > +public: > > + GstreamerMultiStreamTest() > > + : GstreamerTest() > > + { > > + } > > + > > +protected: > > + int init() override > > + { > > + if (status_ != TestPass) > > + return status_; > > + > > + /* Check if platform support multistream output */ > > s/support/supports/ > > s/output/capture/ > > I'll do these changes when applying. > > > Looks good! > > Reviewed-by: Paul Elder <paul.elder@ideasonboard.com> > > > + libcamera::CameraManager cm; > > + cm.start(); > > + bool cameraFound = false; > > + for (auto &camera : cm.cameras()) { > > + if (camera->streams().size() > 1) { > > + cameraName_ = camera->id(); > > + cameraFound = true; > > + cm.stop(); > > + break; > > + } > > + } > > + > > + if (!cameraFound) { > > + cm.stop(); > > + return TestSkip; > > + } > > + > > + const gchar *streamDescription = "queue ! fakesink"; > > + g_autoptr(GError) error = NULL; > > + > > + stream0_ = gst_parse_bin_from_description_full(streamDescription, TRUE, > > + NULL, > > + GST_PARSE_FLAG_FATAL_ERRORS, > > + &error); > > + if (!stream0_) { > > + g_printerr("Stream0 could not be created (%s)\n", error->message); > > + return TestFail; > > + } > > + g_object_ref_sink(stream0_); > > + > > + stream1_ = gst_parse_bin_from_description_full(streamDescription, TRUE, > > + NULL, > > + GST_PARSE_FLAG_FATAL_ERRORS, > > + &error); > > + if (!stream1_) { > > + g_printerr("Stream1 could not be created (%s)\n", error->message); > > + return TestFail; > > + } > > + g_object_ref_sink(stream1_); > > + > > + if (createPipeline() != TestPass) > > + return TestFail; > > + > > + return TestPass; > > + } > > + > > + int run() override > > + { > > + g_object_set(libcameraSrc_, "camera-name", cameraName_.c_str(), NULL); > > + > > + /* Build the pipeline */ > > + gst_bin_add_many(GST_BIN(pipeline_), libcameraSrc_, > > + stream0_, stream1_, NULL); > > + > > + g_autoptr(GstPad) src_pad = gst_element_get_static_pad(libcameraSrc_, "src"); > > + g_autoptr(GstPad) request_pad = gst_element_get_request_pad(libcameraSrc_, "src_%u"); > > + > > + { > > + g_autoptr(GstPad) queue0_sink_pad = gst_element_get_static_pad(stream0_, "sink"); > > + g_autoptr(GstPad) queue1_sink_pad = gst_element_get_static_pad(stream1_, "sink"); > > + > > + if (gst_pad_link(src_pad, queue0_sink_pad) != GST_PAD_LINK_OK || > > + gst_pad_link(request_pad, queue1_sink_pad) != GST_PAD_LINK_OK) { > > + g_printerr("Pads could not be linked.\n"); > > + return TestFail; > > + } > > + } > > + > > + if (startPipeline() != TestPass) > > + return TestFail; > > + > > + if (processEvent() != TestPass) > > + return TestFail; > > + > > + return TestPass; > > + } > > + > > + void cleanup() override > > + { > > + g_clear_object(&stream0_); > > + g_clear_object(&stream1_); > > + } > > + > > +private: > > + std::string cameraName_; > > + GstElement *stream0_; > > + GstElement *stream1_; > > +}; > > + > > +TEST_REGISTER(GstreamerMultiStreamTest) > > diff --git a/test/gstreamer/meson.build b/test/gstreamer/meson.build > > index aca53b920365..10058fc5206f 100644 > > --- a/test/gstreamer/meson.build > > +++ b/test/gstreamer/meson.build > > @@ -6,6 +6,7 @@ endif > > > > gstreamer_tests = [ > > ['single_stream_test', 'gstreamer_single_stream_test.cpp'], > > + ['multi_stream_test', 'gstreamer_multi_stream_test.cpp'], > > ] > > gstreamer_dep = dependency('gstreamer-1.0', required: true) > > > > -- > > 2.25.1 > >
diff --git a/test/gstreamer/gstreamer_multi_stream_test.cpp b/test/gstreamer/gstreamer_multi_stream_test.cpp new file mode 100644 index 000000000000..6a9a6f2509cb --- /dev/null +++ b/test/gstreamer/gstreamer_multi_stream_test.cpp @@ -0,0 +1,124 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2021, Vedant Paranjape + * + * gstreamer_multi_stream_test.cpp - GStreamer multi stream capture test + */ + +#include <iostream> +#include <unistd.h> + +#include <libcamera/libcamera.h> + +#include <gst/gst.h> + +#include "gstreamer_test.h" +#include "test.h" + +using namespace std; + +class GstreamerMultiStreamTest : public GstreamerTest, public Test +{ +public: + GstreamerMultiStreamTest() + : GstreamerTest() + { + } + +protected: + int init() override + { + if (status_ != TestPass) + return status_; + + /* Check if platform support multistream output */ + libcamera::CameraManager cm; + cm.start(); + bool cameraFound = false; + for (auto &camera : cm.cameras()) { + if (camera->streams().size() > 1) { + cameraName_ = camera->id(); + cameraFound = true; + cm.stop(); + break; + } + } + + if (!cameraFound) { + cm.stop(); + return TestSkip; + } + + const gchar *streamDescription = "queue ! fakesink"; + g_autoptr(GError) error = NULL; + + stream0_ = gst_parse_bin_from_description_full(streamDescription, TRUE, + NULL, + GST_PARSE_FLAG_FATAL_ERRORS, + &error); + if (!stream0_) { + g_printerr("Stream0 could not be created (%s)\n", error->message); + return TestFail; + } + g_object_ref_sink(stream0_); + + stream1_ = gst_parse_bin_from_description_full(streamDescription, TRUE, + NULL, + GST_PARSE_FLAG_FATAL_ERRORS, + &error); + if (!stream1_) { + g_printerr("Stream1 could not be created (%s)\n", error->message); + return TestFail; + } + g_object_ref_sink(stream1_); + + if (createPipeline() != TestPass) + return TestFail; + + return TestPass; + } + + int run() override + { + g_object_set(libcameraSrc_, "camera-name", cameraName_.c_str(), NULL); + + /* Build the pipeline */ + gst_bin_add_many(GST_BIN(pipeline_), libcameraSrc_, + stream0_, stream1_, NULL); + + g_autoptr(GstPad) src_pad = gst_element_get_static_pad(libcameraSrc_, "src"); + g_autoptr(GstPad) request_pad = gst_element_get_request_pad(libcameraSrc_, "src_%u"); + + { + g_autoptr(GstPad) queue0_sink_pad = gst_element_get_static_pad(stream0_, "sink"); + g_autoptr(GstPad) queue1_sink_pad = gst_element_get_static_pad(stream1_, "sink"); + + if (gst_pad_link(src_pad, queue0_sink_pad) != GST_PAD_LINK_OK || + gst_pad_link(request_pad, queue1_sink_pad) != GST_PAD_LINK_OK) { + g_printerr("Pads could not be linked.\n"); + return TestFail; + } + } + + if (startPipeline() != TestPass) + return TestFail; + + if (processEvent() != TestPass) + return TestFail; + + return TestPass; + } + + void cleanup() override + { + g_clear_object(&stream0_); + g_clear_object(&stream1_); + } + +private: + std::string cameraName_; + GstElement *stream0_; + GstElement *stream1_; +}; + +TEST_REGISTER(GstreamerMultiStreamTest) diff --git a/test/gstreamer/meson.build b/test/gstreamer/meson.build index aca53b920365..10058fc5206f 100644 --- a/test/gstreamer/meson.build +++ b/test/gstreamer/meson.build @@ -6,6 +6,7 @@ endif gstreamer_tests = [ ['single_stream_test', 'gstreamer_single_stream_test.cpp'], + ['multi_stream_test', 'gstreamer_multi_stream_test.cpp'], ] gstreamer_dep = dependency('gstreamer-1.0', required: true)