Skip to content

Ported GStreamerSource to OpenCV#20709

Merged
alalek merged 8 commits intoopencv:4.xfrom
AsyaPronina:asyadev/integrate_gstreamer_source
Dec 6, 2021
Merged

Ported GStreamerSource to OpenCV#20709
alalek merged 8 commits intoopencv:4.xfrom
AsyaPronina:asyadev/integrate_gstreamer_source

Conversation

@AsyaPronina
Copy link
Copy Markdown
Contributor

@AsyaPronina AsyaPronina commented Sep 16, 2021

Pull Request Readiness Checklist

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

  • I agree to contribute to the project under Apache 2 License.
  • To the best of my knowledge, the proposed patch is not based on a code under GPL or other license that is incompatible with OpenCV
  • The PR is proposed to proper branch
  • There is reference to original bug report and related work
  • There is accuracy test, performance test and test data in opencv_extra repository, if applicable
    Patch to opencv_extra has the same branch name.
  • The feature is well documented and sample code can be built with the project CMake

Build configuration

force_builders=Custom,Custom Win,Custom Mac
build_gapi_standalone:Linux x64=ade-0.1.1f
build_gapi_standalone:Win64=ade-0.1.1f
build_gapi_standalone:Mac=ade-0.1.1f
build_gapi_standalone:Linux x64 Debug=ade-0.1.1f

Xbuild_image:Custom=centos:7
Xbuildworker:Custom=linux-1
build_gapi_standalone:Custom=ade-0.1.1f

build_image:Custom=ubuntu-openvino-2021.4.1:20.04
build_image:Custom Win=openvino-2021.2.0
build_image:Custom Mac=openvino-2021.2.0

test_modules:Custom=gapi,python2,python3,java
test_modules:Custom Win=gapi,python2,python3,java
test_modules:Custom Mac=gapi,python2,python3,java

buildworker:Custom=linux-1
# disabled due high memory usage: test_opencl:Custom=ON
test_opencl:Custom=OFF
test_bigdata:Custom=1
test_filter:Custom=*

This PR is about porting of GStreamer streaming source for G-API pipeline functionality to public OpenCV.

Copy link
Copy Markdown
Contributor

@sivanov-work sivanov-work left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please pay attention about GStreamerPtr assigning pointer ourselves problem at least. Moreover, from my perspective, whole class implementation is danger


void mapBufferToFrame(GstBuffer* buffer, GstVideoInfo* info, GstVideoFrame* frame,
GstMapFlags mapFlags) {
GAPI_Assert(info && "GstVideoInfo is absent during GstBuffer mapping");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can get rid of validity checking by passing references as argument (for buffer and frame also)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed, thanks!

GST_MAP_WRITE);
m_mappedForWrite.store(true, std::memory_order_release);
} else {
gstreamer_utils::mapBufferToFrame(m_buffer, m_videoInfo, &m_videoFrame,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thread 1, R: goes here and make mapBufferToFrame
thread 2, W goes line 67-68 and make gst_video_frame_unmap AND put false in m_isMapped <context switch)
thread 1, R awakes and set m_isMapped to true at line 95.

Does this situation lead to broken invariants?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This situation should never happen according to framework design

GStreamerPtr& operator=(GStreamerPtr&&) = delete;

private:
T* ptr;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How's about to do not use home-grown implementation but default and highly-tested std::unique_ptr with custom dtor :)

tempate<...>
using GStreamerPtr = std::unique_ptr<Type, decltype(GStreamerPtrRelease<Type>)>

make_ptr(Type* ptr) {
return GStreamerPtr (ptr, &GStreamerPtrRelease<Type>);
}

}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is very good suggestion

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed! Thanks!

m_outputType(outputType)
{
auto appsinks = m_pipeline->getElementsByFactoryName("appsink");
GAPI_Assert(1ul == appsinks.size());
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think to add warning log message additionally?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that this is very good idea

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed, thanks!

}
break;
}
default: {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

from my point of view we should handle this situation at construction time

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand, what do you mean here? Could you please add some more details?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure, I mean do not allow to create Source with invalid m_output here
https://github.com/opencv/opencv/pull/20709/files#diff-1387240a1379983779d72695d2b19e9c70195f80ab2784ef8dd3f4885cf78e3fR64

and to remove this switch-case like check from other part of a Source code

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Got the idea

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed, thanks!

gst_app_sink_set_emit_signals(GST_APP_SINK(m_appsink.get()), FALSE);

GStreamerPtr<GstCaps> nv12Caps(gst_caps_from_string(
"video/x-raw,format=NV12;video/x-raw(memory:DMABuf),format=NV12")); /* transfer full */
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggest to make global constant

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed, thanks!

@AsyaPronina AsyaPronina force-pushed the asyadev/integrate_gstreamer_source branch 4 times, most recently from 0557257 to 98ccf8f Compare October 1, 2021 22:29
//
// Copyright 2021 Intel Corporation.
//
// This software and the related documents are Intel copyrighted materials,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use the right license header.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the catch!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed, thanks!

src/streaming/gstreamer/gstreamersource.cpp
src/streaming/gstreamer/gstreamer_buffer_utils.cpp
src/streaming/gstreamer/gstreamer_media_adapter.cpp
src/streaming/gstreamer/gstreamerinit.cpp
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't forget to add:
"${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/streaming/gstreamer/*.hpp" to gapi_ext_hdrs.
Could I also ask you to add:
"${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/streaming/onevpl/*.hpp" to there ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Sure!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, please check!

GStreamerSource(const std::string& pipeline,
const GStreamerSource::OutputType outputType =
GStreamerSource::OutputType::MAT);
GStreamerSource(std::shared_ptr<GStreamerPipelineFacade> pipeline,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the ctor really needed in public section ?
Since there is only forward declaration for GStreamerPipelineFacade it's supposed to be in private section

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, no, this one is used in GStreamerPipeline class, and these classes are not friends.

cv::GComputation c(cv::GIn(in), cv::GOut(out));

// Graph compilation for streaming mode:
auto ccomp = c.compileStreaming(std::move(cv::compile_args(cv::gapi::core::cpu::kernels())));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

U don't need to pass this package explicitly, do you ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I don't, thanks!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed, thanks!

@TolyaTalamanov
Copy link
Copy Markdown
Contributor

I've opened this one: #20832
based on your branch

@TolyaTalamanov
Copy link
Copy Markdown
Contributor

TolyaTalamanov commented Oct 7, 2021

Whitespaces:

modules/gapi/include/opencv2/gapi/streaming/gstreamer/gstreamersource.hpp:33: trailing whitespace.
+ * 
modules/gapi/include/opencv2/gapi/streaming/gstreamer/gstreamersource.hpp:42: trailing whitespace.
+ *        
modules/gapi/include/opencv2/gapi/streaming/gstreamer/gstreamersource.hpp:44: trailing whitespace.
+ * 
modules/gapi/include/opencv2/gapi/streaming/gstreamer/gstreamersource.hpp:51: trailing whitespace.
+ * 
modules/gapi/include/opencv2/gapi/streaming/gstreamer/gstreamersource.hpp:54: trailing whitespace.
+ * 
modules/gapi/include/opencv2/gapi/streaming/gstreamer/gstreamersource.hpp:70: trailing whitespace.
+ 
modules/gapi/src/streaming/gstreamer/gstreamer_pipeline_facade.cpp:62: trailing whitespace.
+// The destructors are noexcept by default (since C++11). 
modules/gapi/src/streaming/gstreamer/gstreamer_pipeline_facade.hpp:69: trailing whitespace.
+    std::string m_pipelineDesc; 
modules/gapi/src/streaming/gstreamer/gstreamerinit.hpp:26: trailing whitespace.
+ * 
modules/gapi/src/streaming/gstreamer/gstreamerinit.hpp:27: trailing whitespace.
+ * 
modules/gapi/src/streaming/gstreamer/gstreamerptr.hpp:69: trailing whitespace.
+{ 
modules/gapi/src/streaming/gstreamer/gstreamersource_priv.hpp:60: trailing whitespace.
+    GstBuffer*                             m_buffer = nullptr; // Actual frame memory holder 
modules/gapi/test/streaming/gapi_gstreamer_pipeline_facade_int_tests.cpp:125: trailing whitespace.
+    GstStateChangeReturn status = 
modules/gapi/test/streaming/gapi_gstreamersource_tests.cpp:66: trailing whitespace.
+    // Streaming - pulling of frames until the end:  
modules/gapi/test/streaming/gapi_gstreamersource_tests.cpp:333: trailing whitespace.
+ 
modules/gapi/test/streaming/gapi_gstreamersource_tests.cpp:339: trailing whitespace.
+    cv::gapi::wip::Data leftImData, rightImData; 
modules/gapi/test/streaming/gapi_gstreamersource_tests.cpp:347: trailing whitespace.
+    std::tuple<cv::GComputation, cv::gapi::wip::GStreamerSource::OutputType> params = GetParam(); 

@AsyaPronina AsyaPronina force-pushed the asyadev/integrate_gstreamer_source branch from 98ccf8f to 37339d2 Compare October 7, 2021 23:30
Copy link
Copy Markdown
Contributor

@sivanov-work sivanov-work left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

"GStreamer pipeline has not been created!");

PipelineState state;
GstClockTime timeout = 5 * GST_SECOND;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then what happened if query state would reach timeout?

}
}

template<typename T> static inline void GStreamerPtrRelease(T** pPtr);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, i mean - use determined specializations for several types of T, but when user or-someone-else just call this function with something not related to correct GStreamer resource, for Foo class for example. Then correct specialization would not be deducted and compiler generated declaration for Foo, which has no body definition and user would face with LINK error, at least

The good approach is do not wait for LINK error but break compilation with some message using static_assert

Something like that:

template<T> GStreamerRelease( T***) {
static_assert(std::is_same<T, ...>::value,  "Unsupported type in GStreamer Release")
}

The part with std::is_same can be more intellectual with variadic templates

Feel free to ignore this comment

}
break;
}
default: {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure, I mean do not allow to create Source with invalid m_output here
https://github.com/opencv/opencv/pull/20709/files#diff-1387240a1379983779d72695d2b19e9c70195f80ab2784ef8dd3f4885cf78e3fR64

and to remove this switch-case like check from other part of a Source code

Comment on lines +34 to +29
* To create GStreamerSource instance you need to pass 'pipeline' and, optionally, 'outputType'
* arguments into constructor.
* 'pipeline' should represent GStreamer pipeline in form of textual description.
* Almost any custom pipeline is supported which can be successfully ran via gst-launch.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* To create GStreamerSource instance you need to pass 'pipeline' and, optionally, 'outputType'
* arguments into constructor.
* 'pipeline' should represent GStreamer pipeline in form of textual description.
* Almost any custom pipeline is supported which can be successfully ran via gst-launch.
* To create a GStreamerSource instance you need to pass 'pipeline' and, optionally, 'outputType'
* arguments into constructor.
* 'pipeline' should represent a GStreamer pipeline in form of textual description.
* Almost any custom pipeline is supported which can be successfully run via gst-launch.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is irregular verb, this is why "ran" is used here

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but here is 3rd form needed, which is "run"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please consider to correct

@AsyaPronina AsyaPronina force-pushed the asyadev/integrate_gstreamer_source branch 5 times, most recently from ff807b5 to 7c22705 Compare October 11, 2021 09:20
@AsyaPronina
Copy link
Copy Markdown
Contributor Author

@AsyaPronina
Copy link
Copy Markdown
Contributor Author


#ifndef OPENCV_GAPI_STREAMING_GSTREAMER_GStreamerEnv_HPP
#define OPENCV_GAPI_STREAMING_GSTREAMER_GStreamerEnv_HPP

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#ifdef HAVE_GSTREAMER?

Copy link
Copy Markdown
Contributor

@OrestChura OrestChura left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great!

Comment on lines +34 to +29
* To create GStreamerSource instance you need to pass 'pipeline' and, optionally, 'outputType'
* arguments into constructor.
* 'pipeline' should represent GStreamer pipeline in form of textual description.
* Almost any custom pipeline is supported which can be successfully ran via gst-launch.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please consider to correct

@AsyaPronina AsyaPronina force-pushed the asyadev/integrate_gstreamer_source branch 5 times, most recently from 6cf3d58 to 0dd69f1 Compare November 14, 2021 21:58
@AsyaPronina AsyaPronina force-pushed the asyadev/integrate_gstreamer_source branch from 0dd69f1 to 7a38fb0 Compare November 22, 2021 13:23
@dmatveev dmatveev added this to the 4.5.5 milestone Nov 26, 2021
pipelineFacade.completePreroll();

cv::gapi::wip::gst::GStreamerPtr<GstSample> prerollSample(
// gst_app_sink_try_pull_preroll(GST_APP_SINK(appsink), 5 * GST_SECOND));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Debug code?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for a catch!! This code should be version-dependent!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed!

@OrestChura
Copy link
Copy Markdown
Contributor

👍🏻

Comment on lines +336 to +338
std::tuple<cv::GComputation, cv::gapi::wip::GStreamerSource::OutputType> params = GetParam();
cv::GComputation extractImage = std::move(std::get<0>(params));
cv::gapi::wip::GStreamerSource::OutputType outputType = std::get<1>(params);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can std::tie() be used here instead?

Suggested change
std::tuple<cv::GComputation, cv::gapi::wip::GStreamerSource::OutputType> params = GetParam();
cv::GComputation extractImage = std::move(std::get<0>(params));
cv::gapi::wip::GStreamerSource::OutputType outputType = std::get<1>(params);
cv::GComputation extractImage;
cv::gapi::wip::GStreamerSource::OutputType outputType = /*default value*/ 0;
std::tie(extractImage, outputType ) = GetParam();

Is it because GComputation can't be declared like that?

@dmatveev dmatveev self-assigned this Dec 6, 2021
Copy link
Copy Markdown
Contributor

@dmatveev dmatveev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Merge this please

@alalek
Copy link
Copy Markdown
Member

alalek commented Dec 6, 2021

PR should not be merged in current form due to broken compilation in Custom builder with GStreamer:

/build/precommit_custom_linux/4.x/opencv/modules/gapi/test/streaming/gapi_gstreamer_pipeline_facade_int_tests.cpp: In member function 'virtual void opencv_test::GStreamerPipelineFacadeTest_CompletePrerollUnitTest_Test::Body()':
/build/precommit_custom_linux/4.x/opencv/modules/gapi/test/streaming/gapi_gstreamer_pipeline_facade_int_tests.cpp:95:13: error: 'gst_app_sink_try_pull_prerollGST_APP_SINK' was not declared in this scope; did you mean 'gst_app_sink_try_pull_preroll'?
   95 |             gst_app_sink_try_pull_prerollGST_APP_SINK(appsink), 5 * GST_SECOND));
      |             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |             gst_app_sink_try_pull_preroll
/build/precommit_custom_linux/4.x/opencv/modules/gapi/test/streaming/gapi_gstreamer_pipeline_facade_int_tests.cpp:95:80: error: expected ',' or ';' before ')' token
   95 |             gst_app_sink_try_pull_prerollGST_APP_SINK(appsink), 5 * GST_SECOND));
      |                                                                                ^
make[2]: *** [modules/gapi/CMakeFiles/opencv_test_gapi.dir/build.make:1025: modules/gapi/CMakeFiles/opencv_test_gapi.dir/test/streaming/gapi_gstreamer_pipeline_facade_int_tests.cpp.o] Error 1

@AsyaPronina AsyaPronina force-pushed the asyadev/integrate_gstreamer_source branch from 5309176 to 97fadfc Compare December 6, 2021 14:42
@alalek alalek merged commit 8dd6882 into opencv:4.x Dec 6, 2021
@alalek alalek mentioned this pull request Dec 30, 2021
@alalek alalek mentioned this pull request Feb 22, 2022
a-sajjad72 pushed a commit to a-sajjad72/opencv that referenced this pull request Mar 30, 2023
…treamer_source

Ported GStreamerSource to OpenCV

* Ported GStreamerSource to OpenCV

* Fixed CI failures

* Whitespaces

* Whitespaces + removed exception from destructors C4722

* Removed assert for Priv's getSS and descr_of

* Removed assert for pull

* Fixed last review comment

Co-authored-by: Pashchenkov Maxim <maxim.pashchenkov@intel.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants