| /* 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" |
| |
| #if !GST_CHECK_VERSION(1, 19, 1) |
| static inline GstPad *gst_element_request_pad_simple(GstElement *element, |
| const gchar *name) |
| { |
| return gst_element_get_request_pad(element, name); |
| } |
| #endif |
| |
| using namespace std; |
| |
| class GstreamerMultiStreamTest : public GstreamerTest, public Test |
| { |
| public: |
| GstreamerMultiStreamTest() |
| : GstreamerTest() |
| { |
| } |
| |
| protected: |
| int init() override |
| { |
| if (status_ != TestPass) |
| return status_; |
| |
| /* Check if platform supports multistream capture */ |
| 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_request_pad_simple(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) |