├── NOTICE
├── Samples
├── twocameras_compositor
│ ├── vs
│ │ ├── twocameras_compositor.vcxproj.filters
│ │ └── twocameras_compositor.vcxproj
│ ├── Makefile
│ └── twocameras_compositor.cpp
├── simplegrab
│ ├── Makefile
│ ├── vs
│ │ ├── simplegrab.vcxproj.filters
│ │ └── simplegrab.vcxproj
│ └── simplegrab.cpp
├── simplegrab_tx2
│ ├── Makefile
│ ├── vs
│ │ ├── simplegrab_tx2.vcxproj.filters
│ │ └── simplegrab_tx2.vcxproj
│ └── simplegrab_tx2.cpp
├── demopylongstreamer
│ ├── Makefile
│ ├── vs
│ │ ├── demopylongstreamer.vcxproj.filters
│ │ └── demopylongstreamer.vcxproj
│ ├── CPipelineHelper.h
│ ├── CPipelineHelper.cpp
│ └── demopylongstreamer.cpp
└── demopylongstreamer_jetson_performance
│ ├── Makefile
│ ├── vs
│ ├── demopylongstreamer.vcxproj.filters
│ └── demopylongstreamer.vcxproj
│ ├── CPipelineHelper.h
│ ├── CInstantCameraAppSrc.h
│ ├── CPipelineHelper.cpp
│ ├── demopylongstreamer.cpp
│ └── acA5472-17ucO_22860864.pfs
├── InstantCameraAppSrc
└── CInstantCameraAppSrc.h
├── README.md
├── .gitignore
└── LICENSE
/NOTICE:
--------------------------------------------------------------------------------
1 | THIS SOFTWARE REQUIRES "ADDITIONAL SOFTWARE" (IE: LIBRARIES) IN ORDER TO COMPILE
2 | INTO BINARY FORM AND TO FUNCTION IN BINARY FORM. ANY SUCH "ADDITIONAL SOFTWARE"
3 | IS OUTSIDE THE SCOPE OF THIS SOFTWARE'S LICENSE.
--------------------------------------------------------------------------------
/Samples/twocameras_compositor/vs/twocameras_compositor.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {5cf31861-7d5c-4a07-94e1-0350d1f60631}
6 |
7 |
8 | {c679736a-bd70-409a-bae6-a6a8785f8e5f}
9 |
10 |
11 |
12 |
13 | Header Files
14 |
15 |
16 |
17 |
18 | Source Files
19 |
20 |
21 | Source Files
22 |
23 |
24 |
--------------------------------------------------------------------------------
/Samples/simplegrab/Makefile:
--------------------------------------------------------------------------------
1 | # Makefile for simplegrab
2 | .PHONY: all clean
3 |
4 | # The program to build
5 | NAME := simplegrab
6 | CLASS1 := ../../InstantCameraAppSrc/CInstantCameraAppSrc
7 |
8 | # Installation directories for pylon
9 | PYLON_ROOT ?= /opt/pylon5
10 | DIR ?= /usr/include
11 |
12 | # Build tools and flags
13 | LD := $(CXX)
14 | CPPFLAGS := $(shell pkg-config --cflags gstreamer-1.0 gstreamer-app-1.0) $(shell $(PYLON_ROOT)/bin/pylon-config --cflags) -std=c++11
15 | CXXFLAGS := #e.g., CXXFLAGS=-g -O0 for debugging
16 | LDFLAGS := $(shell $(PYLON_ROOT)/bin/pylon-config --libs-rpath)
17 | LDLIBS := $(shell pkg-config --libs gstreamer-1.0 gstreamer-app-1.0) $(shell $(PYLON_ROOT)/bin/pylon-config --libs)
18 |
19 | # Rules for building
20 | all: $(NAME)
21 |
22 | $(NAME): $(NAME).o $(CLASS1).o
23 | $(LD) $(LDFLAGS) -o $@ $^ $(LDLIBS)
24 |
25 | $(NAME).o: $(NAME).cpp $(CLASS1).cpp
26 | $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
27 |
28 | clean:
29 | $(RM) $(NAME).o $(CLASS1).o $(CLASS2).o $(NAME)
30 |
--------------------------------------------------------------------------------
/Samples/simplegrab_tx2/Makefile:
--------------------------------------------------------------------------------
1 | # Makefile for simplegrab_tx2
2 | .PHONY: all clean
3 |
4 | # The program to build
5 | NAME := simplegrab_tx2
6 | CLASS1 := ../../InstantCameraAppSrc/CInstantCameraAppSrc
7 |
8 | # Installation directories for pylon
9 | PYLON_ROOT ?= /opt/pylon5
10 | DIR ?= /usr/include
11 |
12 | # Build tools and flags
13 | LD := $(CXX)
14 | CPPFLAGS := $(shell pkg-config --cflags gstreamer-1.0 gstreamer-app-1.0) $(shell $(PYLON_ROOT)/bin/pylon-config --cflags) -std=c++11
15 | CXXFLAGS := #e.g., CXXFLAGS=-g -O0 for debugging
16 | LDFLAGS := $(shell $(PYLON_ROOT)/bin/pylon-config --libs-rpath)
17 | LDLIBS := $(shell pkg-config --libs gstreamer-1.0 gstreamer-app-1.0) $(shell $(PYLON_ROOT)/bin/pylon-config --libs)
18 |
19 | # Rules for building
20 | all: $(NAME)
21 |
22 | $(NAME): $(NAME).o $(CLASS1).o
23 | $(LD) $(LDFLAGS) -o $@ $^ $(LDLIBS)
24 |
25 | $(NAME).o: $(NAME).cpp $(CLASS1).cpp
26 | $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
27 |
28 | clean:
29 | $(RM) $(NAME).o $(CLASS1).o $(CLASS2).o $(NAME)
30 |
--------------------------------------------------------------------------------
/Samples/twocameras_compositor/Makefile:
--------------------------------------------------------------------------------
1 | # Makefile for twocameras_compositor
2 | .PHONY: all clean
3 |
4 | # The program to build
5 | NAME := twocameras_compositor
6 | CLASS1 := ../../InstantCameraAppSrc/CInstantCameraAppSrc
7 |
8 | # Installation directories for pylon
9 | PYLON_ROOT ?= /opt/pylon5
10 | DIR ?= /usr/include
11 |
12 | # Build tools and flags
13 | LD := $(CXX)
14 | CPPFLAGS := $(shell pkg-config --cflags gstreamer-1.0 gstreamer-app-1.0) $(shell $(PYLON_ROOT)/bin/pylon-config --cflags) -std=c++11
15 | CXXFLAGS := #e.g., CXXFLAGS=-g -O0 for debugging
16 | LDFLAGS := $(shell $(PYLON_ROOT)/bin/pylon-config --libs-rpath)
17 | LDLIBS := $(shell pkg-config --libs gstreamer-1.0 gstreamer-app-1.0) $(shell $(PYLON_ROOT)/bin/pylon-config --libs)
18 |
19 | # Rules for building
20 | all: $(NAME)
21 |
22 | $(NAME): $(NAME).o $(CLASS1).o
23 | $(LD) $(LDFLAGS) -o $@ $^ $(LDLIBS)
24 |
25 | $(NAME).o: $(NAME).cpp $(CLASS1).cpp
26 | $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
27 |
28 | clean:
29 | $(RM) $(NAME).o $(CLASS1).o $(CLASS2).o $(NAME)
30 |
--------------------------------------------------------------------------------
/Samples/demopylongstreamer/Makefile:
--------------------------------------------------------------------------------
1 | # Makefile for demopylongstreamer
2 | .PHONY: all clean
3 |
4 | # The program to build
5 | NAME := demopylongstreamer
6 | CLASS1 := ../../InstantCameraAppSrc/CInstantCameraAppSrc
7 | CLASS2 := CPipelineHelper
8 |
9 | # Installation directories for pylon
10 | PYLON_ROOT ?= /opt/pylon5
11 | DIR ?= /usr/include
12 |
13 | # Build tools and flags
14 | LD := $(CXX)
15 | CPPFLAGS := $(shell pkg-config --cflags gstreamer-1.0 gstreamer-app-1.0) $(shell $(PYLON_ROOT)/bin/pylon-config --cflags) -std=c++11
16 | CXXFLAGS := #e.g., CXXFLAGS=-g -O0 for debugging
17 | LDFLAGS := $(shell $(PYLON_ROOT)/bin/pylon-config --libs-rpath)
18 | LDLIBS := $(shell pkg-config --libs gstreamer-1.0 gstreamer-app-1.0) $(shell $(PYLON_ROOT)/bin/pylon-config --libs)
19 |
20 | # Rules for building
21 | all: $(NAME)
22 |
23 | $(NAME): $(NAME).o $(CLASS1).o $(CLASS2).o
24 | $(LD) $(LDFLAGS) -o $@ $^ $(LDLIBS)
25 |
26 | $(NAME).o: $(NAME).cpp $(CLASS1).cpp $(CLASS2).cpp
27 | $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
28 |
29 | clean:
30 | $(RM) $(NAME).o $(CLASS1).o $(CLASS2).o $(NAME)
31 |
--------------------------------------------------------------------------------
/Samples/demopylongstreamer_jetson_performance/Makefile:
--------------------------------------------------------------------------------
1 | # Makefile for demopylongstreamer
2 | .PHONY: all clean
3 |
4 | # The program to build
5 | NAME := demopylongstreamer
6 | CLASS1 := CInstantCameraAppSrc
7 | CLASS2 := CPipelineHelper
8 |
9 | # Installation directories for pylon
10 | PYLON_ROOT ?= /opt/pylon6_2_0
11 | DIR ?= /usr/include
12 |
13 | # Build tools and flags
14 | LD := $(CXX)
15 | CPPFLAGS := $(shell pkg-config --cflags gstreamer-1.0 gstreamer-app-1.0) $(shell $(PYLON_ROOT)/bin/pylon-config --cflags) -std=c++11
16 | CXXFLAGS := #e.g., CXXFLAGS=-g -O0 for debugging
17 | LDFLAGS := $(shell $(PYLON_ROOT)/bin/pylon-config --libs-rpath)
18 | LDLIBS := $(shell pkg-config --libs gstreamer-1.0 gstreamer-app-1.0) $(shell $(PYLON_ROOT)/bin/pylon-config --libs)
19 |
20 | # Rules for building
21 | all: $(NAME)
22 |
23 | $(NAME): $(NAME).o $(CLASS1).o $(CLASS2).o
24 | $(LD) $(LDFLAGS) -o $@ $^ $(LDLIBS)
25 |
26 | $(NAME).o: $(NAME).cpp $(CLASS1).cpp $(CLASS2).cpp
27 | $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
28 |
29 | clean:
30 | $(RM) $(NAME).o $(CLASS1).o $(CLASS2).o $(NAME)
31 |
--------------------------------------------------------------------------------
/Samples/demopylongstreamer_jetson_performance/vs/demopylongstreamer.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {41386959-fb3c-4e4e-84a8-08aceea5d5f1}
10 |
11 |
12 |
13 |
14 | Source Files
15 |
16 |
17 | Source Files
18 |
19 |
20 | Source Files
21 |
22 |
23 |
24 |
25 | Header Files
26 |
27 |
28 | Header Files
29 |
30 |
31 |
--------------------------------------------------------------------------------
/Samples/demopylongstreamer/vs/demopylongstreamer.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {41386959-fb3c-4e4e-84a8-08aceea5d5f1}
10 |
11 |
12 |
13 |
14 | Source Files
15 |
16 |
17 | Source Files
18 |
19 |
20 | Source Files
21 |
22 |
23 |
24 |
25 | Header Files
26 |
27 |
28 | Header Files
29 |
30 |
31 |
--------------------------------------------------------------------------------
/Samples/simplegrab/vs/simplegrab.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {bbcc4f0b-973b-48ba-a5aa-5cd8777082c1}
10 |
11 |
12 | {b2c6bf18-0244-41a6-afbf-47800ec9b69e}
13 |
14 |
15 |
16 |
17 | Docs
18 |
19 |
20 | Docs
21 |
22 |
23 |
24 |
25 | Source Files
26 |
27 |
28 | Source Files
29 |
30 |
31 |
32 |
33 | Header Files
34 |
35 |
36 |
--------------------------------------------------------------------------------
/Samples/simplegrab_tx2/vs/simplegrab_tx2.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {bbcc4f0b-973b-48ba-a5aa-5cd8777082c1}
10 |
11 |
12 | {b2c6bf18-0244-41a6-afbf-47800ec9b69e}
13 |
14 |
15 |
16 |
17 | Docs
18 |
19 |
20 | Docs
21 |
22 |
23 |
24 |
25 | Source Files
26 |
27 |
28 | Source Files
29 |
30 |
31 |
32 |
33 | Header Files
34 |
35 |
36 |
--------------------------------------------------------------------------------
/Samples/demopylongstreamer/CPipelineHelper.h:
--------------------------------------------------------------------------------
1 | /* CPipelineHelper.h: header file for CPipelineHeader Class.
2 | Given a GStreamer pipeline and source, this will finish building a pipeline.
3 |
4 | Copyright 2017 Matthew Breit
5 |
6 | Licensed under the Apache License, Version 2.0 (the "License");
7 | you may not use this file except in compliance with the License.
8 | You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing, software
13 | distributed under the License is distributed on an "AS IS" BASIS,
14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | See the License for the specific language governing permissions and
16 | limitations under the License.
17 |
18 | THIS SOFTWARE REQUIRES ADDITIONAL SOFTWARE (IE: LIBRARIES) IN ORDER TO COMPILE
19 | INTO BINARY FORM AND TO FUNCTION IN BINARY FORM. ANY SUCH ADDITIONAL SOFTWARE
20 | IS OUTSIDE THE SCOPE OF THIS LICENSE.
21 | */
22 |
23 | #include
24 | #include
25 | #include
26 |
27 | using namespace std;
28 |
29 | // Given a pipeline and source, this class will finish building pipelines of various elements for various purposes.
30 |
31 | class CPipelineHelper
32 | {
33 | public:
34 | CPipelineHelper(GstElement *pipeline, GstElement *source);
35 | ~CPipelineHelper();
36 |
37 | // example of how to create a pipeline for display in a window
38 | bool build_pipeline_display();
39 |
40 | // example of how to create a pipeline for piping images to a linux framebuffer
41 | bool build_pipeline_framebuffer(string fbDevice);
42 |
43 | // example of how to create a pipeline for encoding images in h264 format and streaming across a network
44 | bool build_pipeline_h264stream(string ipAddress);
45 |
46 | // example of how to create a pipeline for encoding images in h264 format and multicast across a network
47 | bool build_pipeline_h264multicast(string ipAddress);
48 |
49 | // example of how to create a pipeline for encoding images in h264 format and streaming to local video file
50 | bool build_pipeline_h264file(string fileName);
51 |
52 | // example of how to create a pipeline from a string that you would use with gst-launch-1.0
53 | bool build_pipeline_parsestring(string pipelineString);
54 |
55 | private:
56 | bool m_pipelineBuilt;
57 | GstElement *m_pipeline;
58 | GstElement *m_source;
59 | };
60 |
--------------------------------------------------------------------------------
/Samples/demopylongstreamer_jetson_performance/CPipelineHelper.h:
--------------------------------------------------------------------------------
1 | /* CPipelineHelper.h: header file for CPipelineHeader Class.
2 | Given a GStreamer pipeline and source, this will finish building a pipeline.
3 |
4 | Copyright 2017 Matthew Breit
5 |
6 | Licensed under the Apache License, Version 2.0 (the "License");
7 | you may not use this file except in compliance with the License.
8 | You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing, software
13 | distributed under the License is distributed on an "AS IS" BASIS,
14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | See the License for the specific language governing permissions and
16 | limitations under the License.
17 |
18 | THIS SOFTWARE REQUIRES ADDITIONAL SOFTWARE (IE: LIBRARIES) IN ORDER TO COMPILE
19 | INTO BINARY FORM AND TO FUNCTION IN BINARY FORM. ANY SUCH ADDITIONAL SOFTWARE
20 | IS OUTSIDE THE SCOPE OF THIS LICENSE.
21 | */
22 |
23 | #include
24 | #include
25 | #include
26 |
27 | using namespace std;
28 |
29 | // Given a pipeline and source, this class will finish building pipelines of various elements for various purposes.
30 |
31 | class CPipelineHelper
32 | {
33 | public:
34 | CPipelineHelper(GstElement *pipeline, GstElement *source);
35 | ~CPipelineHelper();
36 |
37 | // example of how to create a pipeline for display in a window
38 | bool build_pipeline_display();
39 |
40 | // example of how to create a pipeline for piping images to a linux framebuffer
41 | bool build_pipeline_framebuffer(string fbDevice);
42 |
43 | // example of how to create a pipeline for encoding images in h264 format and streaming across a network
44 | bool build_pipeline_h264stream(string ipAddress);
45 |
46 | // example of how to create a pipeline for encoding images in h264 format and multicast across a network
47 | bool build_pipeline_h264multicast(string ipAddress);
48 |
49 | // example of how to create a pipeline for encoding images in h264 format and streaming to local video file
50 | bool build_pipeline_h264file(string fileName);
51 |
52 | // example of how to create a pipeline from a string that you would use with gst-launch-1.0
53 | bool build_pipeline_parsestring(string pipelineString);
54 |
55 | private:
56 | bool m_pipelineBuilt;
57 | GstElement *m_pipeline;
58 | GstElement *m_source;
59 | };
60 |
--------------------------------------------------------------------------------
/InstantCameraAppSrc/CInstantCameraAppSrc.h:
--------------------------------------------------------------------------------
1 | /* CInstantCameraAppSrc.h: header file for CInstantCameraAppSrc Class.
2 | This will extend the Basler Pylon::CInstantCamera Class to make it more convinient to use with GstAppSrc.
3 |
4 | Copyright 2017 Matthew Breit
5 |
6 | Licensed under the Apache License, Version 2.0 (the "License");
7 | you may not use this file except in compliance with the License.
8 | You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing, software
13 | distributed under the License is distributed on an "AS IS" BASIS,
14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | See the License for the specific language governing permissions and
16 | limitations under the License.
17 |
18 | THIS SOFTWARE REQUIRES ADDITIONAL SOFTWARE (IE: LIBRARIES) IN ORDER TO COMPILE
19 | INTO BINARY FORM AND TO FUNCTION IN BINARY FORM. ANY SUCH ADDITIONAL SOFTWARE
20 | IS OUTSIDE THE SCOPE OF THIS LICENSE.
21 |
22 | */
23 |
24 | #include
25 | #include
26 |
27 | using namespace Pylon;
28 | using namespace GenApi;
29 | using namespace std;
30 |
31 | // ******* CInstantCameraAppSrc *******
32 | // Here we extend the Pylon CInstantCamera class with a few things to make it easier to integrate with Appsrc.
33 | class CInstantCameraAppSrc : public CInstantCamera
34 | {
35 | public:
36 | CInstantCameraAppSrc(string serialnumber = "");
37 | ~CInstantCameraAppSrc();
38 |
39 | int GetWidth();
40 | int GetHeight();
41 | bool InitCamera(
42 | int width,
43 | int height,
44 | int framesPerSecond,
45 | bool useOnDemand,
46 | bool useTrigger,
47 | int scaledWidth = -1,
48 | int scaledHeight = -1,
49 | int rotation = -1,
50 | int numFramesToGrab = -1);
51 | bool StartCamera();
52 | bool StopCamera();
53 | bool OpenCamera();
54 | bool CloseCamera();
55 | bool ResetCamera();
56 | bool SetFrameRate(double framesPerSecond);
57 | bool AutoAdjustImage();
58 | bool SaveSettingsToCamera(bool BootWithNewSettings = false);
59 | double GetFrameRate();
60 | GstElement* GetSource();
61 |
62 | private:
63 | int m_width;
64 | int m_height;
65 | int m_frameRate;
66 | int m_scaledWidth;
67 | int m_scaledHeight;
68 | int m_rotation;
69 | int m_numFramesToGrab;
70 | bool m_isInitialized;
71 | bool m_isColor;
72 | bool m_isOnDemand;
73 | bool m_isTriggered;
74 | bool m_isOpen;
75 | string m_serialNumber;
76 | Pylon::CPylonImage m_Image;
77 | Pylon::CImageFormatConverter m_FormatConverter;
78 | GstElement* m_appsrc;
79 | GstElement* m_sourceBin;
80 | GstBuffer* m_gstBuffer;
81 | bool retrieve_image();
82 | static void cb_need_data(GstElement *appsrc, guint unused_size, gpointer user_data);
83 | };
84 |
--------------------------------------------------------------------------------
/Samples/demopylongstreamer_jetson_performance/CInstantCameraAppSrc.h:
--------------------------------------------------------------------------------
1 | /* CInstantCameraAppSrc.h: header file for CInstantCameraAppSrc Class.
2 | This will extend the Basler Pylon::CInstantCamera Class to make it more convinient to use with GstAppSrc.
3 |
4 | Copyright 2017 Matthew Breit
5 |
6 | Licensed under the Apache License, Version 2.0 (the "License");
7 | you may not use this file except in compliance with the License.
8 | You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing, software
13 | distributed under the License is distributed on an "AS IS" BASIS,
14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | See the License for the specific language governing permissions and
16 | limitations under the License.
17 |
18 | THIS SOFTWARE REQUIRES ADDITIONAL SOFTWARE (IE: LIBRARIES) IN ORDER TO COMPILE
19 | INTO BINARY FORM AND TO FUNCTION IN BINARY FORM. ANY SUCH ADDITIONAL SOFTWARE
20 | IS OUTSIDE THE SCOPE OF THIS LICENSE.
21 |
22 | */
23 |
24 | #include
25 | #include
26 |
27 | using namespace Pylon;
28 | using namespace GenApi;
29 | using namespace std;
30 |
31 | // ******* CInstantCameraAppSrc *******
32 | // Here we extend the Pylon CInstantCamera class with a few things to make it easier to integrate with Appsrc.
33 | class CInstantCameraAppSrc : public CInstantCamera
34 | {
35 | public:
36 | CInstantCameraAppSrc(string serialnumber = "");
37 | ~CInstantCameraAppSrc();
38 |
39 | int GetWidth();
40 | int GetHeight();
41 | bool InitCamera(
42 | int width,
43 | int height,
44 | int framesPerSecond,
45 | bool useOnDemand,
46 | bool useTrigger,
47 | int scaledWidth = -1,
48 | int scaledHeight = -1,
49 | int rotation = -1,
50 | int numFramesToGrab = -1);
51 | bool StartCamera();
52 | bool StopCamera();
53 | bool OpenCamera();
54 | bool CloseCamera();
55 | bool ResetCamera();
56 | bool SetFrameRate(double framesPerSecond);
57 | bool AutoAdjustImage();
58 | bool SaveSettingsToCamera(bool BootWithNewSettings = false);
59 | double GetFrameRate();
60 | GstElement* GetSource();
61 |
62 | private:
63 | int m_width;
64 | int m_height;
65 | int m_frameRate;
66 | int m_scaledWidth;
67 | int m_scaledHeight;
68 | int m_rotation;
69 | int m_numFramesToGrab;
70 | bool m_isInitialized;
71 | bool m_isColor;
72 | bool m_isOnDemand;
73 | bool m_isTriggered;
74 | bool m_isOpen;
75 | string m_serialNumber;
76 | Pylon::CPylonImage m_Image;
77 | Pylon::CImageFormatConverter m_FormatConverter;
78 | GstElement* m_appsrc;
79 | GstElement* m_sourceBin;
80 | GstBuffer* m_gstBuffer;
81 | bool retrieve_image();
82 | static void cb_need_data(GstElement *appsrc, guint unused_size, gpointer user_data);
83 | };
84 |
--------------------------------------------------------------------------------
/Samples/twocameras_compositor/vs/twocameras_compositor.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Pylon5Release
6 | x64
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | twocameras_compositor
18 | {9CE2A9A4-2EFB-4EF7-B54D-6B44317D4B59}
19 | simplegrab
20 |
21 |
22 |
23 | Application
24 | v120
25 | MultiByte
26 | true
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | <_ProjectFileVersion>12.0.21005.1
37 |
38 |
39 | $(SolutionDir)$(Configuration)_$(Platform)\
40 | $(Configuration)_$(Platform)\
41 | false
42 |
43 |
44 |
45 | X64
46 |
47 |
48 | MaxSpeed
49 | $(GSTREAMER_1_0_ROOT_X86_64)\include\glib-2.0;$(GSTREAMER_1_0_ROOT_X86_64)\lib\glib-2.0\include;$(GSTREAMER_1_0_ROOT_X86_64)\include\gstreamer-1.0;$(PYLON_DEV_DIR)\include;(AdditionalIncludeDirectories)
50 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
51 | MultiThreadedDLL
52 | true
53 |
54 |
55 | Level3
56 | ProgramDatabase
57 |
58 |
59 | $(PYLON_DEV_DIR)\lib\x64;$(GSTREAMER_1_0_ROOT_X86_64)\lib;$(GSTREAMER_1_0_ROOT_X86_64)\lib\glib-2.0;$(GSTREAMER_1_0_ROOT_X86_64)\lib\gstreamer-1.0\static;%(AdditionalLibraryDirectories)
60 | %(DelayLoadDLLs)
61 | true
62 | Console
63 | true
64 | true
65 | MachineX64
66 | gstreamer-1.0.lib;gstbase-1.0.lib;glib-2.0.lib;gobject-2.0.lib;%(AdditionalDependencies)
67 |
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/Samples/demopylongstreamer_jetson_performance/vs/demopylongstreamer.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Pylon5Release
6 | x64
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | demopylongstreamer
20 | {9CE2A9A4-2EFB-4EF7-B54D-6B44317D4B59}
21 | pylongstreamer
22 |
23 |
24 |
25 | Application
26 | v120
27 | MultiByte
28 | true
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | <_ProjectFileVersion>12.0.21005.1
39 |
40 |
41 | $(SolutionDir)$(Configuration)_$(Platform)\
42 | $(Configuration)_$(Platform)\
43 | false
44 |
45 |
46 |
47 | X64
48 |
49 |
50 | MaxSpeed
51 | $(GSTREAMER_1_0_ROOT_X86_64)\include\glib-2.0;$(GSTREAMER_1_0_ROOT_X86_64)\lib\glib-2.0\include;$(GSTREAMER_1_0_ROOT_X86_64)\include\gstreamer-1.0;$(PYLON_DEV_DIR)\include;(AdditionalIncludeDirectories)
52 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
53 | MultiThreadedDLL
54 | true
55 |
56 |
57 | Level3
58 | ProgramDatabase
59 |
60 |
61 | $(PYLON_DEV_DIR)\lib\x64;$(GSTREAMER_1_0_ROOT_X86_64)\lib;$(GSTREAMER_1_0_ROOT_X86_64)\lib\glib-2.0;$(GSTREAMER_1_0_ROOT_X86_64)\lib\gstreamer-1.0\static;%(AdditionalLibraryDirectories)
62 | %(DelayLoadDLLs)
63 | true
64 | Console
65 | true
66 | true
67 | MachineX64
68 | gstreamer-1.0.lib;gstbase-1.0.lib;glib-2.0.lib;gobject-2.0.lib;%(AdditionalDependencies)
69 |
70 |
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/Samples/simplegrab/vs/simplegrab.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Pylon5Release
6 | x64
7 |
8 |
9 |
10 | simplegrab
11 | {9CE2A9A4-2EFB-4EF7-B54D-6B44317D4B59}
12 | simplegrab
13 |
14 |
15 |
16 | Application
17 | v120
18 | MultiByte
19 | true
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | <_ProjectFileVersion>12.0.21005.1
30 |
31 |
32 | $(SolutionDir)$(Configuration)_$(Platform)\
33 | $(Configuration)_$(Platform)\
34 | false
35 |
36 |
37 |
38 | X64
39 |
40 |
41 | MaxSpeed
42 | $(GSTREAMER_1_0_ROOT_X86_64)\include\glib-2.0;$(GSTREAMER_1_0_ROOT_X86_64)\lib\glib-2.0\include;$(GSTREAMER_1_0_ROOT_X86_64)\include\gstreamer-1.0;$(PYLON_DEV_DIR)\include;(AdditionalIncludeDirectories)
43 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
44 | MultiThreadedDLL
45 | true
46 |
47 |
48 | Level3
49 | ProgramDatabase
50 |
51 |
52 | $(PYLON_DEV_DIR)\lib\x64;$(GSTREAMER_1_0_ROOT_X86_64)\lib;$(GSTREAMER_1_0_ROOT_X86_64)\lib\glib-2.0;$(GSTREAMER_1_0_ROOT_X86_64)\lib\gstreamer-1.0\static;%(AdditionalLibraryDirectories)
53 | %(DelayLoadDLLs)
54 | true
55 | Console
56 | true
57 | true
58 | MachineX64
59 | gstreamer-1.0.lib;gstbase-1.0.lib;glib-2.0.lib;gobject-2.0.lib;%(AdditionalDependencies)
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/Samples/demopylongstreamer/vs/demopylongstreamer.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Pylon5Release
6 | x64
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | demopylongstreamer
20 | {9CE2A9A4-2EFB-4EF7-B54D-6B44317D4B59}
21 | pylongstreamer
22 |
23 |
24 |
25 | Application
26 | v120
27 | MultiByte
28 | true
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | <_ProjectFileVersion>12.0.21005.1
39 |
40 |
41 | $(SolutionDir)$(Configuration)_$(Platform)\
42 | $(Configuration)_$(Platform)\
43 | false
44 |
45 |
46 |
47 | X64
48 |
49 |
50 | MaxSpeed
51 | $(GSTREAMER_1_0_ROOT_X86_64)\include\glib-2.0;$(GSTREAMER_1_0_ROOT_X86_64)\lib\glib-2.0\include;$(GSTREAMER_1_0_ROOT_X86_64)\include\gstreamer-1.0;$(PYLON_DEV_DIR)\include;(AdditionalIncludeDirectories)
52 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
53 | MultiThreadedDLL
54 | true
55 |
56 |
57 | Level3
58 | ProgramDatabase
59 |
60 |
61 | $(PYLON_DEV_DIR)\lib\x64;$(GSTREAMER_1_0_ROOT_X86_64)\lib;$(GSTREAMER_1_0_ROOT_X86_64)\lib\glib-2.0;$(GSTREAMER_1_0_ROOT_X86_64)\lib\gstreamer-1.0\static;%(AdditionalLibraryDirectories)
62 | %(DelayLoadDLLs)
63 | true
64 | Console
65 | true
66 | true
67 | MachineX64
68 | gstreamer-1.0.lib;gstbase-1.0.lib;glib-2.0.lib;gobject-2.0.lib;%(AdditionalDependencies)
69 |
70 |
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/Samples/simplegrab_tx2/vs/simplegrab_tx2.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Pylon5Release
6 | x64
7 |
8 |
9 |
10 | simplegrab_tx2
11 | {9CE2A9A4-2EFB-4EF7-B54D-6B44317D4B59}
12 | simplegrab
13 |
14 |
15 |
16 | Application
17 | v120
18 | MultiByte
19 | true
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | <_ProjectFileVersion>12.0.21005.1
30 |
31 |
32 | $(SolutionDir)$(Configuration)_$(Platform)\
33 | $(Configuration)_$(Platform)\
34 | false
35 |
36 |
37 |
38 | X64
39 |
40 |
41 | MaxSpeed
42 | $(GSTREAMER_1_0_ROOT_X86_64)\include\glib-2.0;$(GSTREAMER_1_0_ROOT_X86_64)\lib\glib-2.0\include;$(GSTREAMER_1_0_ROOT_X86_64)\include\gstreamer-1.0;$(PYLON_DEV_DIR)\include;(AdditionalIncludeDirectories)
43 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
44 | MultiThreadedDLL
45 | true
46 |
47 |
48 | Level3
49 | ProgramDatabase
50 |
51 |
52 | $(PYLON_DEV_DIR)\lib\x64;$(GSTREAMER_1_0_ROOT_X86_64)\lib;$(GSTREAMER_1_0_ROOT_X86_64)\lib\glib-2.0;$(GSTREAMER_1_0_ROOT_X86_64)\lib\gstreamer-1.0\static;%(AdditionalLibraryDirectories)
53 | %(DelayLoadDLLs)
54 | true
55 | Console
56 | true
57 | true
58 | MachineX64
59 | gstreamer-1.0.lib;gstbase-1.0.lib;glib-2.0.lib;gobject-2.0.lib;%(AdditionalDependencies)
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Using Pylon with GStreamer: The InstantCameraAppSrc class
2 | - The InstantCameraAppSrc class presents the Basler camera as a source element for GStreamer pipelines.
3 | - It combines Pylon's InstantCamera class with GStreamer's AppSrc plugin.
4 | - The InstantCamera class offers access to physical camera functions and Pylon driver functions.
5 | - The AppSrc plugin offers an API to bring user-defined images, data, etc. into GStreamer pipelines.
6 | - InstantCameraAppSrc can be extended via the GenApi to access any camera and driver feature (eg: GetFrameRate()).
7 | - InstantCameraAppSrc cab be extended via GStreamer "bins" to include any other plugins within the source element (eg: Rescale, Rotate, etc.)
8 |
9 | # Architecture
10 | ```
11 | |<--------------- Camera Acquisition & Pylon Grabbing ------------------->|<---------------------------------------- GStreamer Pipeline ------------------------->|
12 | |<------------------------------------------------------------- CInstantCameraAppSrc --------------------------------------->|
13 | +-------------------------------------------------------------------------+--------------------------------------------------+ +----------+ +---------------+
14 | | GetGstAppSrc()---------> sourceBin element | | other | | sink element |
15 | | | | | elements | | |
16 | | RetrieveImage()<---cb_need_data()<---------"need-data" signal | | | | |
17 | | ------------------> --> 1. RetrieveResult() | | | | | |
18 | | | LatestImageOnly | 2. Convert to RGB if color | | | | | |
19 | | <------------------ 3. Put into a [pylonimage] | +-------------+ +------------+ +------------+ | | | | |
20 | | [Camera]-->[Pylon Grab Engine] 4. Wrap in a gst buffer | | | | | | | | | | | |
21 | | --------> 5. "push-buffer" signal-------------------->AppSrc-------->Rescale------->Rotate------>src--sink src--sink |
22 | | |freerun| | | | | | | | | | | | |
23 | | <-------- | +-------------+ +------------+ +------------+ | | | | |
24 | +-------------------------------------------------------------------------+--------------------------------------------------+ +----------+ +---------------+
25 | ```
26 |
27 | # Sample Programs
28 | - Sample programs based on the InstantCameraAppSrc class are found in the Samples folder.
29 | - "DemoPylonGStreamer" is a rich demonstration of possibilities, including a "PipelineHelper" class to assist in making pipelines.
30 | - "SimpleGrab" is an example of the bare minimum code needed to create a GStreamer application.
31 | - Linux makefiles are included for each sample application.
32 | - Windows Visual Studio project files are included for each sample application in the respective "vs" folder.
33 |
34 | # Requirements
35 | - Linux x86/x64/ARM or Windows 7/10. (OSX has not been tested.)
36 | - Pylon 5.0.9 or higher on Linux. Pylon 5.0.10 or higher on Windows. (Older versions down to Pylon 3.0 may work, but are untested.)
37 | - GStreamer 1.0. (GStreamer 0.1 may work, but is untested.)
38 | - Note for Linux users: You may need to install the following libraries:
39 | gstreamer1.0
40 | gstreamer1.0-dev
41 | gstreamer1.0-libav
42 | gstreamer1.0-plugins-bad
43 | libgstreamer-plugins-base1.0-dev
44 | (on Ubuntu systems, all can be isntalled using apt-get install)
45 |
46 | # Note about GStreamer Plugins (elements)
47 | - All systems are different. Some GStreamer pipeline plugins used in the Sample Programs may not exist on your system!
48 | - As a result, you may see errors like "Not Negotiated", etc. when running the samples.
49 | - Consult GStreamer directly for more information: https://gstreamer.freedesktop.org/
50 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.suo
8 | *.user
9 | *.userosscache
10 | *.sln.docstates
11 |
12 | # User-specific files (MonoDevelop/Xamarin Studio)
13 | *.userprefs
14 |
15 | # Build results
16 | [Dd]ebug/
17 | [Dd]ebugPublic/
18 | [Rr]elease/
19 | [Rr]eleases/
20 | x64/
21 | x86/
22 | bld/
23 | [Bb]in/
24 | [Oo]bj/
25 | [Ll]og/
26 |
27 | # Visual Studio 2015 cache/options directory
28 | .vs/
29 | # Uncomment if you have tasks that create the project's static files in wwwroot
30 | #wwwroot/
31 |
32 | # MSTest test Results
33 | [Tt]est[Rr]esult*/
34 | [Bb]uild[Ll]og.*
35 |
36 | # NUNIT
37 | *.VisualState.xml
38 | TestResult.xml
39 |
40 | # Build Results of an ATL Project
41 | [Dd]ebugPS/
42 | [Rr]eleasePS/
43 | dlldata.c
44 |
45 | # .NET Core
46 | project.lock.json
47 | project.fragment.lock.json
48 | artifacts/
49 | **/Properties/launchSettings.json
50 |
51 | *_i.c
52 | *_p.c
53 | *_i.h
54 | *.ilk
55 | *.meta
56 | *.obj
57 | *.pch
58 | *.pdb
59 | *.pgc
60 | *.pgd
61 | *.rsp
62 | *.sbr
63 | *.tlb
64 | *.tli
65 | *.tlh
66 | *.tmp
67 | *.tmp_proj
68 | *.log
69 | *.vspscc
70 | *.vssscc
71 | .builds
72 | *.pidb
73 | *.svclog
74 | *.scc
75 |
76 | # Chutzpah Test files
77 | _Chutzpah*
78 |
79 | # Visual C++ cache files
80 | ipch/
81 | *.aps
82 | *.ncb
83 | *.opendb
84 | *.opensdf
85 | *.sdf
86 | *.cachefile
87 | *.VC.db
88 | *.VC.VC.opendb
89 |
90 | # Visual Studio profiler
91 | *.psess
92 | *.vsp
93 | *.vspx
94 | *.sap
95 |
96 | # TFS 2012 Local Workspace
97 | $tf/
98 |
99 | # Guidance Automation Toolkit
100 | *.gpState
101 |
102 | # ReSharper is a .NET coding add-in
103 | _ReSharper*/
104 | *.[Rr]e[Ss]harper
105 | *.DotSettings.user
106 |
107 | # JustCode is a .NET coding add-in
108 | .JustCode
109 |
110 | # TeamCity is a build add-in
111 | _TeamCity*
112 |
113 | # DotCover is a Code Coverage Tool
114 | *.dotCover
115 |
116 | # Visual Studio code coverage results
117 | *.coverage
118 | *.coveragexml
119 |
120 | # NCrunch
121 | _NCrunch_*
122 | .*crunch*.local.xml
123 | nCrunchTemp_*
124 |
125 | # MightyMoose
126 | *.mm.*
127 | AutoTest.Net/
128 |
129 | # Web workbench (sass)
130 | .sass-cache/
131 |
132 | # Installshield output folder
133 | [Ee]xpress/
134 |
135 | # DocProject is a documentation generator add-in
136 | DocProject/buildhelp/
137 | DocProject/Help/*.HxT
138 | DocProject/Help/*.HxC
139 | DocProject/Help/*.hhc
140 | DocProject/Help/*.hhk
141 | DocProject/Help/*.hhp
142 | DocProject/Help/Html2
143 | DocProject/Help/html
144 |
145 | # Click-Once directory
146 | publish/
147 |
148 | # Publish Web Output
149 | *.[Pp]ublish.xml
150 | *.azurePubxml
151 | # TODO: Comment the next line if you want to checkin your web deploy settings
152 | # but database connection strings (with potential passwords) will be unencrypted
153 | *.pubxml
154 | *.publishproj
155 |
156 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
157 | # checkin your Azure Web App publish settings, but sensitive information contained
158 | # in these scripts will be unencrypted
159 | PublishScripts/
160 |
161 | # NuGet Packages
162 | *.nupkg
163 | # The packages folder can be ignored because of Package Restore
164 | **/packages/*
165 | # except build/, which is used as an MSBuild target.
166 | !**/packages/build/
167 | # Uncomment if necessary however generally it will be regenerated when needed
168 | #!**/packages/repositories.config
169 | # NuGet v3's project.json files produces more ignorable files
170 | *.nuget.props
171 | *.nuget.targets
172 |
173 | # Microsoft Azure Build Output
174 | csx/
175 | *.build.csdef
176 |
177 | # Microsoft Azure Emulator
178 | ecf/
179 | rcf/
180 |
181 | # Windows Store app package directories and files
182 | AppPackages/
183 | BundleArtifacts/
184 | Package.StoreAssociation.xml
185 | _pkginfo.txt
186 |
187 | # Visual Studio cache files
188 | # files ending in .cache can be ignored
189 | *.[Cc]ache
190 | # but keep track of directories ending in .cache
191 | !*.[Cc]ache/
192 |
193 | # Others
194 | ClientBin/
195 | ~$*
196 | *~
197 | *.dbmdl
198 | *.dbproj.schemaview
199 | *.jfm
200 | *.pfx
201 | *.publishsettings
202 | orleans.codegen.cs
203 |
204 | # Since there are multiple workflows, uncomment next line to ignore bower_components
205 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
206 | #bower_components/
207 |
208 | # RIA/Silverlight projects
209 | Generated_Code/
210 |
211 | # Backup & report files from converting an old project file
212 | # to a newer Visual Studio version. Backup files are not needed,
213 | # because we have git ;-)
214 | _UpgradeReport_Files/
215 | Backup*/
216 | UpgradeLog*.XML
217 | UpgradeLog*.htm
218 |
219 | # SQL Server files
220 | *.mdf
221 | *.ldf
222 | *.ndf
223 |
224 | # Business Intelligence projects
225 | *.rdl.data
226 | *.bim.layout
227 | *.bim_*.settings
228 |
229 | # Microsoft Fakes
230 | FakesAssemblies/
231 |
232 | # GhostDoc plugin setting file
233 | *.GhostDoc.xml
234 |
235 | # Node.js Tools for Visual Studio
236 | .ntvs_analysis.dat
237 | node_modules/
238 |
239 | # Typescript v1 declaration files
240 | typings/
241 |
242 | # Visual Studio 6 build log
243 | *.plg
244 |
245 | # Visual Studio 6 workspace options file
246 | *.opt
247 |
248 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
249 | *.vbw
250 |
251 | # Visual Studio LightSwitch build output
252 | **/*.HTMLClient/GeneratedArtifacts
253 | **/*.DesktopClient/GeneratedArtifacts
254 | **/*.DesktopClient/ModelManifest.xml
255 | **/*.Server/GeneratedArtifacts
256 | **/*.Server/ModelManifest.xml
257 | _Pvt_Extensions
258 |
259 | # Paket dependency manager
260 | .paket/paket.exe
261 | paket-files/
262 |
263 | # FAKE - F# Make
264 | .fake/
265 |
266 | # JetBrains Rider
267 | .idea/
268 | *.sln.iml
269 |
270 | # CodeRush
271 | .cr/
272 |
273 | # Python Tools for Visual Studio (PTVS)
274 | __pycache__/
275 | *.pyc
276 |
277 | # Cake - Uncomment if you are using it
278 | # tools/**
279 | # !tools/packages.config
280 |
281 | # Telerik's JustMock configuration file
282 | *.jmconfig
283 |
284 | # BizTalk build output
285 | *.btp.cs
286 | *.btm.cs
287 | *.odx.cs
288 | *.xsd.cs
289 |
--------------------------------------------------------------------------------
/Samples/simplegrab/simplegrab.cpp:
--------------------------------------------------------------------------------
1 | /* simplegrab.cpp: Sample application using CInstantCameraAppSrc class.
2 | This will grab and display images.
3 |
4 | Copyright 2018 Matthew Breit
5 |
6 | Licensed under the Apache License, Version 2.0 (the "License");
7 | you may not use this file except in compliance with the License.
8 | You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing, software
13 | distributed under the License is distributed on an "AS IS" BASIS,
14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | See the License for the specific language governing permissions and
16 | limitations under the License.
17 |
18 | THIS SOFTWARE REQUIRES ADDITIONAL SOFTWARE (IE: LIBRARIES) IN ORDER TO COMPILE
19 | INTO BINARY FORM AND TO FUNCTION IN BINARY FORM. ANY SUCH ADDITIONAL SOFTWARE
20 | IS OUTSIDE THE SCOPE OF THIS LICENSE.
21 |
22 |
23 | Concept Overview:
24 | <--------------- InstantCameraAppSrc --------------> <------------ GStreamer Pipeline ------->
25 | +--------------------------------------------------+ +---------+ +---------+ +---------+
26 | | source | | element | | element | | sink |
27 | | (camera + driver + GstAppSrc + rescale + rotate) | | | | | | |
28 | | src--sink src--sink src--sink |
29 | +--------------------------------------------------+ +---------+ +---------+ +---------+
30 |
31 | Note:
32 | Some GStreamer elements (plugins) used in the pipeline examples may not be available on all systems. Consult GStreamer for more information:
33 | https://gstreamer.freedesktop.org/
34 | */
35 |
36 |
37 | #include "../../InstantCameraAppSrc/CInstantCameraAppSrc.h"
38 | #include
39 |
40 | using namespace std;
41 |
42 | int exitCode = 0;
43 |
44 | // ******* variables, call-backs, etc. for use with gstreamer ********
45 | // The main event loop manages all the available sources of events for GLib and GTK+ applications
46 | GMainLoop *loop;
47 | // The GstBus is an object responsible for delivering GstMessage packets in a first-in first-out way from the streaming threads
48 | GstBus *bus;
49 | guint bus_watch_id;
50 |
51 | // we link elements together in a pipeline, and send messages to/from the pipeline.
52 | GstElement *pipeline;
53 |
54 | // handler for bus call messages
55 | gboolean bus_call(GstBus *bus, GstMessage *msg, gpointer data)
56 | {
57 | try
58 | {
59 | GMainLoop *loop = (GMainLoop *)data;
60 |
61 | switch (GST_MESSAGE_TYPE(msg)) {
62 |
63 | case GST_MESSAGE_EOS:
64 | g_print("End of stream\n");
65 | g_main_loop_quit(loop);
66 | break;
67 |
68 | case GST_MESSAGE_ERROR: {
69 | gchar *debug;
70 | GError *error;
71 |
72 | gst_message_parse_error(msg, &error, &debug);
73 | g_printerr ("ERROR from element %s: %s\n", GST_OBJECT_NAME (msg->src), error->message);
74 | g_printerr ("Debugging info: %s\n", (debug) ? debug : "none");
75 |
76 | g_error_free(error);
77 | g_free(debug);
78 |
79 | g_main_loop_quit(loop);
80 | break;
81 | }
82 |
83 | default:
84 | break;
85 | }
86 |
87 | return TRUE;
88 | }
89 | catch (std::exception &e)
90 | {
91 | cerr << "An exception occurred in bus_call(): " << endl << e.what() << endl;
92 | return FALSE;
93 | }
94 | }
95 |
96 | static void sigint_restore()
97 | {
98 | try
99 | {
100 | #ifndef WIN32
101 | struct sigaction action;
102 | memset(&action, 0, sizeof(action));
103 | action.sa_handler = SIG_DFL;
104 | sigaction(SIGINT, &action, NULL);
105 | #endif
106 | }
107 | catch (std::exception &e)
108 | {
109 | cerr << "An exception occurred in sigint_restore(): " << endl << e.what() << endl;
110 | }
111 | }
112 |
113 | // Signal handler for ctrl+c
114 | void IntHandler(int dummy)
115 | {
116 | try
117 | {
118 | // send End Of Stream event to all pipeline elements
119 | cout << endl;
120 | cout << "Sending EOS event to pipeline..." << endl;
121 | gst_element_send_event(pipeline, gst_event_new_eos());
122 | sigint_restore();
123 | return;
124 | }
125 | catch (std::exception &e)
126 | {
127 | cerr << "An exception occurred in IntHandler(): " << endl << e.what() << endl;
128 | }
129 | }
130 |
131 | // ******* END variables, call-backs, etc. for use with gstreamer ********
132 |
133 | gint main(gint argc, gchar *argv[])
134 | {
135 | try
136 | {
137 | // signal handler for ctrl+C
138 | signal(SIGINT, IntHandler);
139 |
140 | cout << "Press CTRL+C at any time to quit." << endl;
141 |
142 | // initialize GStreamer
143 | gst_init(NULL, NULL);
144 |
145 | // create the mainloop
146 | loop = g_main_loop_new(NULL, FALSE);
147 |
148 | // The InstantCameraForAppSrc will manage the physical camera and pylon driver
149 | // and provide a source element to the GStreamer pipeline.
150 | CInstantCameraAppSrc camera;
151 |
152 | // Initialize the camera and driver
153 | cout << "Initializing camera and driver..." << endl;
154 |
155 | // use the GenICam API to access features because it supports any interface (USB, GigE, etc.)
156 | // reset the camera to defaults if you like
157 | camera.ResetCamera();
158 | // use maximum width and height
159 | int width = GenApi::CIntegerPtr(camera.GetNodeMap().GetNode("Width"))->GetMax();
160 | int height = GenApi::CIntegerPtr(camera.GetNodeMap().GetNode("Height"))->GetMax();
161 | int frameRate = 30; // We will try for 30fps. The actual camera capabilities depend on it's settings...
162 |
163 | camera.InitCamera(width, height, frameRate, false, false, 320, 240);
164 |
165 | cout << "Using Camera : " << camera.GetDeviceInfo().GetFriendlyName() << endl;
166 | cout << "Camera Area Of Interest : " << camera.GetWidth() << "x" << camera.GetHeight() << endl;
167 | cout << "Camera Speed : " << camera.GetFrameRate() << " fps" << endl;
168 |
169 | // create a new pipeline to add elements too
170 | pipeline = gst_pipeline_new("pipeline");
171 |
172 | // prepare a handler (watcher) for messages from the pipeline
173 | bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));
174 | bus_watch_id = gst_bus_add_watch(bus, bus_call, loop);
175 | gst_object_unref(bus);
176 |
177 | // A pipeline needs a source element. The InstantCameraForAppSrc will create, configure, and provide an AppSrc which fits the camera.
178 | GstElement *source = camera.GetSource();
179 |
180 | // Create the other needed gstreamer pipeline elements
181 | GstElement *convert;
182 | GstElement *sink;
183 | convert = gst_element_factory_make("videoconvert", "converter");
184 | sink = gst_element_factory_make("autovideosink", "videosink"); // depending on your platform, you may have to use some alternative here, like ("autovideosink", "sink")
185 |
186 | if (!convert){ cout << "Could not make convert" << endl; return false; }
187 | if (!sink){ cout << "Could not make sink" << endl; return false; }
188 |
189 | // add and link the pipeline elements
190 | gst_bin_add_many(GST_BIN(pipeline), source, convert, sink, NULL);
191 | gst_element_link_many(source, convert, sink, NULL);
192 |
193 |
194 | // Start the camera and grab engine.
195 | if (camera.StartCamera() == false)
196 | {
197 | exitCode = -1;
198 | throw std::runtime_error("Could not start camera!");
199 | }
200 |
201 | // Start the pipeline.
202 | cout << "Starting pipeline..." << endl;
203 | gst_element_set_state(pipeline, GST_STATE_PLAYING);
204 |
205 | // run the main loop. When Ctrl+C is pressed, an EOS event will be sent
206 | // which will shutdown the pipeline in intHandler(), which will in turn quit the main loop.
207 | g_main_loop_run(loop);
208 |
209 | // clean up
210 | cout << "Stopping pipeline..." << endl;
211 | gst_element_set_state(pipeline, GST_STATE_NULL);
212 |
213 | camera.StopCamera();
214 | camera.CloseCamera();
215 |
216 | gst_object_unref(GST_OBJECT(pipeline));
217 | g_main_loop_unref(loop);
218 |
219 | exitCode = 0;
220 |
221 | }
222 | catch (GenICam::GenericException &e)
223 | {
224 | cerr << "An exception occured in main(): " << endl << e.GetDescription() << endl;
225 | exitCode = -1;
226 | }
227 | catch (std::exception &e)
228 | {
229 | cerr << "An exception occurred in main(): " << endl << e.what() << endl;
230 | exitCode = -1;
231 | }
232 |
233 | // Comment the following two lines to disable waiting on exit.
234 | cerr << endl << "Press Enter to exit." << endl;
235 | while (cin.get() != '\n');
236 |
237 | return exitCode;
238 | }
239 |
--------------------------------------------------------------------------------
/Samples/simplegrab_tx2/simplegrab_tx2.cpp:
--------------------------------------------------------------------------------
1 | /* simplegrab_tx2.cpp: Sample application using CInstantCameraAppSrc class.
2 | This will grab and display images.
3 |
4 | Copyright 2018 Matthew Breit
5 |
6 | Licensed under the Apache License, Version 2.0 (the "License");
7 | you may not use this file except in compliance with the License.
8 | You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing, software
13 | distributed under the License is distributed on an "AS IS" BASIS,
14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | See the License for the specific language governing permissions and
16 | limitations under the License.
17 |
18 | THIS SOFTWARE REQUIRES ADDITIONAL SOFTWARE (IE: LIBRARIES) IN ORDER TO COMPILE
19 | INTO BINARY FORM AND TO FUNCTION IN BINARY FORM. ANY SUCH ADDITIONAL SOFTWARE
20 | IS OUTSIDE THE SCOPE OF THIS LICENSE.
21 |
22 |
23 | Concept Overview:
24 | <--------------- InstantCameraAppSrc --------------> <------------ GStreamer Pipeline ------->
25 | +--------------------------------------------------+ +---------+ +---------+ +---------+
26 | | source | | element | | element | | sink |
27 | | (camera + driver + GstAppSrc + rescale + rotate) | | | | | | |
28 | | src--sink src--sink src--sink |
29 | +--------------------------------------------------+ +---------+ +---------+ +---------+
30 |
31 | Note:
32 | Some GStreamer elements (plugins) used in the pipeline examples may not be available on all systems. Consult GStreamer for more information:
33 | https://gstreamer.freedesktop.org/
34 | */
35 |
36 |
37 | #include "../../InstantCameraAppSrc/CInstantCameraAppSrc.h"
38 | #include
39 |
40 | using namespace std;
41 |
42 | int exitCode = 0;
43 |
44 | // ******* variables, call-backs, etc. for use with gstreamer ********
45 | // The main event loop manages all the available sources of events for GLib and GTK+ applications
46 | GMainLoop *loop;
47 | // The GstBus is an object responsible for delivering GstMessage packets in a first-in first-out way from the streaming threads
48 | GstBus *bus;
49 | guint bus_watch_id;
50 |
51 | // we link elements together in a pipeline, and send messages to/from the pipeline.
52 | GstElement *pipeline;
53 |
54 | // handler for bus call messages
55 | gboolean bus_call(GstBus *bus, GstMessage *msg, gpointer data)
56 | {
57 | try
58 | {
59 | GMainLoop *loop = (GMainLoop *)data;
60 |
61 | switch (GST_MESSAGE_TYPE(msg)) {
62 |
63 | case GST_MESSAGE_EOS:
64 | g_print("End of stream\n");
65 | g_main_loop_quit(loop);
66 | break;
67 |
68 | case GST_MESSAGE_ERROR: {
69 | gchar *debug;
70 | GError *error;
71 |
72 | gst_message_parse_error(msg, &error, &debug);
73 | g_printerr ("ERROR from element %s: %s\n", GST_OBJECT_NAME (msg->src), error->message);
74 | g_printerr ("Debugging info: %s\n", (debug) ? debug : "none");
75 |
76 | g_error_free(error);
77 | g_free(debug);
78 |
79 | g_main_loop_quit(loop);
80 | break;
81 | }
82 |
83 | default:
84 | break;
85 | }
86 |
87 | return TRUE;
88 | }
89 | catch (std::exception &e)
90 | {
91 | cerr << "An exception occurred in bus_call(): " << endl << e.what() << endl;
92 | return FALSE;
93 | }
94 | }
95 |
96 | static void sigint_restore()
97 | {
98 | try
99 | {
100 | #ifndef WIN32
101 | struct sigaction action;
102 | memset(&action, 0, sizeof(action));
103 | action.sa_handler = SIG_DFL;
104 | sigaction(SIGINT, &action, NULL);
105 | #endif
106 | }
107 | catch (std::exception &e)
108 | {
109 | cerr << "An exception occurred in sigint_restore(): " << endl << e.what() << endl;
110 | }
111 | }
112 |
113 | // Signal handler for ctrl+c
114 | void IntHandler(int dummy)
115 | {
116 | try
117 | {
118 | // send End Of Stream event to all pipeline elements
119 | cout << endl;
120 | cout << "Sending EOS event to pipeline..." << endl;
121 | gst_element_send_event(pipeline, gst_event_new_eos());
122 | sigint_restore();
123 | return;
124 | }
125 | catch (std::exception &e)
126 | {
127 | cerr << "An exception occurred in IntHandler(): " << endl << e.what() << endl;
128 | }
129 | }
130 |
131 | // ******* END variables, call-backs, etc. for use with gstreamer ********
132 |
133 | gint main(gint argc, gchar *argv[])
134 | {
135 | try
136 | {
137 | // signal handler for ctrl+C
138 | signal(SIGINT, IntHandler);
139 |
140 | cout << "Press CTRL+C at any time to quit." << endl;
141 |
142 | // initialize GStreamer
143 | gst_init(NULL, NULL);
144 |
145 | // create the mainloop
146 | loop = g_main_loop_new(NULL, FALSE);
147 |
148 | // The InstantCameraForAppSrc will manage the physical camera and pylon driver
149 | // and provide a source element to the GStreamer pipeline.
150 | CInstantCameraAppSrc camera;
151 |
152 | // Initialize the camera and driver
153 | cout << "Initializing camera and driver..." << endl;
154 |
155 | // use the GenICam API to access features because it supports any interface (USB, GigE, etc.)
156 | // reset the camera to defaults if you like
157 | camera.ResetCamera();
158 | // use maximum width and height
159 | int width = GenApi::CIntegerPtr(camera.GetNodeMap().GetNode("Width"))->GetMax();
160 | int height = GenApi::CIntegerPtr(camera.GetNodeMap().GetNode("Height"))->GetMax();
161 | int frameRate = 30; // we will try for this framerate, but the actual camera's capabilities will depend on other settings...
162 |
163 | camera.InitCamera(width, height, frameRate, false, false, 320, 240);
164 |
165 | cout << "Using Camera : " << camera.GetDeviceInfo().GetFriendlyName() << endl;
166 | cout << "Camera Area Of Interest : " << camera.GetWidth() << "x" << camera.GetHeight() << endl;
167 | cout << "Camera Speed : " << camera.GetFrameRate() << " fps" << endl;
168 |
169 | // create a new pipeline to add elements too
170 | pipeline = gst_pipeline_new("pipeline");
171 |
172 | // prepare a handler (watcher) for messages from the pipeline
173 | bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));
174 | bus_watch_id = gst_bus_add_watch(bus, bus_call, loop);
175 | gst_object_unref(bus);
176 |
177 | // A pipeline needs a source element. The InstantCameraForAppSrc will create, configure, and provide an AppSrc which fits the camera.
178 | GstElement *source = camera.GetSource();
179 |
180 | // Create the other needed gstreamer pipeline elements
181 | GstElement *convert;
182 | GstElement *sink;
183 | convert = gst_element_factory_make("videoconvert", "converter");
184 | sink = gst_element_factory_make("autovideosink", "videosink"); // depending on your platform, you may have to use some alternative here, like ("autovideosink", "sink")
185 |
186 | if (!convert){ cout << "Could not make convert" << endl; return false; }
187 | if (!sink){ cout << "Could not make sink" << endl; return false; }
188 |
189 | // Nvidia TX1/TX2 Note: The built-in video sink that is found by autovideosink does not advertise that it needs conversion (it does not support RGB).
190 | // so we must use a filter such that the converter knows to convert the image format.
191 | // if you are using a video sink that supports RGB, then you do not need to convert to i420 and you can remove this filter and save some cpu load.
192 | GstElement *filter;
193 | GstCaps *filter_caps;
194 | filter = gst_element_factory_make("capsfilter", "filter");
195 | filter_caps = gst_caps_new_simple("video/x-raw", "format", G_TYPE_STRING, "I420", NULL);
196 | g_object_set(G_OBJECT(filter), "caps", filter_caps, NULL);
197 | gst_caps_unref(filter_caps);
198 |
199 | // add and link the pipeline elements
200 | gst_bin_add_many(GST_BIN(pipeline), source, convert, filter, sink, NULL);
201 | gst_element_link_many(source, convert, filter, sink, NULL);
202 |
203 | // Start the camera and grab engine.
204 | if (camera.StartCamera() == false)
205 | {
206 | exitCode = -1;
207 | throw std::runtime_error("Could not start camera!");
208 | }
209 |
210 | // Start the pipeline.
211 | cout << "Starting pipeline..." << endl;
212 | gst_element_set_state(pipeline, GST_STATE_PLAYING);
213 |
214 | // run the main loop. When Ctrl+C is pressed, an EOS event will be sent
215 | // which will shutdown the pipeline in intHandler(), which will in turn quit the main loop.
216 | g_main_loop_run(loop);
217 |
218 | // clean up
219 | cout << "Stopping pipeline..." << endl;
220 | gst_element_set_state(pipeline, GST_STATE_NULL);
221 |
222 | camera.StopCamera();
223 | camera.CloseCamera();
224 |
225 | gst_object_unref(GST_OBJECT(pipeline));
226 | g_main_loop_unref(loop);
227 |
228 | exitCode = 0;
229 |
230 | }
231 | catch (GenICam::GenericException &e)
232 | {
233 | cerr << "An exception occured in main(): " << endl << e.GetDescription() << endl;
234 | exitCode = -1;
235 | }
236 | catch (std::exception &e)
237 | {
238 | cerr << "An exception occurred in main(): " << endl << e.what() << endl;
239 | exitCode = -1;
240 | }
241 |
242 | // Comment the following two lines to disable waiting on exit.
243 | cerr << endl << "Press Enter to exit." << endl;
244 | while (cin.get() != '\n');
245 |
246 | return exitCode;
247 | }
248 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
--------------------------------------------------------------------------------
/Samples/twocameras_compositor/twocameras_compositor.cpp:
--------------------------------------------------------------------------------
1 | /* twocameras_compositor.cpp: Sample application using CInstantCameraAppSrc class.
2 | This will grab and display images from two cameras.
3 |
4 | Copyright 2018 Matthew Breit
5 |
6 | Licensed under the Apache License, Version 2.0 (the "License");
7 | you may not use this file except in compliance with the License.
8 | You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing, software
13 | distributed under the License is distributed on an "AS IS" BASIS,
14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | See the License for the specific language governing permissions and
16 | limitations under the License.
17 |
18 | THIS SOFTWARE REQUIRES ADDITIONAL SOFTWARE (IE: LIBRARIES) IN ORDER TO COMPILE
19 | INTO BINARY FORM AND TO FUNCTION IN BINARY FORM. ANY SUCH ADDITIONAL SOFTWARE
20 | IS OUTSIDE THE SCOPE OF THIS LICENSE.
21 |
22 |
23 | Concept Overview:
24 | <--------------- InstantCameraAppSrc --------------> <------------ GStreamer Pipeline ------->
25 | +--------------------------------------------------+ +---------+ +---------+ +---------+
26 | | source | | element | | element | | sink |
27 | | (camera + driver + GstAppSrc + rescale + rotate) | | | | | | |
28 | | src--sink src--sink src--sink |
29 | +--------------------------------------------------+ +---------+ +---------+ +---------+
30 |
31 | Note:
32 | Some GStreamer elements (plugins) used in the pipeline examples may not be available on all systems. Consult GStreamer for more information:
33 | https://gstreamer.freedesktop.org/
34 | */
35 |
36 |
37 | #include "../../InstantCameraAppSrc/CInstantCameraAppSrc.h"
38 | #include
39 | #include
40 |
41 | using namespace std;
42 |
43 | int exitCode = 0;
44 |
45 | // ******* variables, call-backs, etc. for use with gstreamer ********
46 | // The main event loop manages all the available sources of events for GLib and GTK+ applications
47 | GMainLoop *loop;
48 | // The GstBus is an object responsible for delivering GstMessage packets in a first-in first-out way from the streaming threads
49 | GstBus *bus;
50 | guint bus_watch_id;
51 |
52 | // we link elements together in a pipeline, and send messages to/from the pipeline.
53 | GstElement *pipeline;
54 |
55 | // handler for bus call messages
56 | gboolean bus_call(GstBus *bus, GstMessage *msg, gpointer data)
57 | {
58 | try
59 | {
60 | GMainLoop *loop = (GMainLoop *)data;
61 |
62 | gchar *debug;
63 | GError *error;
64 |
65 | switch (GST_MESSAGE_TYPE(msg)) {
66 |
67 | case GST_MESSAGE_EOS:
68 | g_print("End of stream\n");
69 | g_main_loop_quit(loop);
70 | break;
71 |
72 | case GST_MESSAGE_ERROR: {
73 | gchar *debug;
74 | GError *error;
75 |
76 | gst_message_parse_error(msg, &error, &debug);
77 | g_printerr ("ERROR from element %s: %s\n", GST_OBJECT_NAME (msg->src), error->message);
78 | g_printerr ("Debugging info: %s\n", (debug) ? debug : "none");
79 |
80 | g_error_free(error);
81 | g_free(debug);
82 |
83 | g_main_loop_quit(loop);
84 | break;
85 | }
86 |
87 | default:
88 | break;
89 | }
90 |
91 | return TRUE;
92 | }
93 | catch (std::exception &e)
94 | {
95 | cerr << "An exception occurred in bus_call(): " << endl << e.what() << endl;
96 | return FALSE;
97 | }
98 | }
99 |
100 | static void sigint_restore()
101 | {
102 | try
103 | {
104 | #ifndef WIN32
105 | struct sigaction action;
106 | memset(&action, 0, sizeof(action));
107 | action.sa_handler = SIG_DFL;
108 | sigaction(SIGINT, &action, NULL);
109 | #endif
110 | }
111 | catch (std::exception &e)
112 | {
113 | cerr << "An exception occurred in sigint_restore(): " << endl << e.what() << endl;
114 | }
115 | }
116 |
117 | // Signal handler for ctrl+c
118 | void IntHandler(int dummy)
119 | {
120 | try
121 | {
122 | // send End Of Stream event to all pipeline elements
123 | cout << endl;
124 | cout << "Sending EOS event to pipeline..." << endl;
125 | gst_element_send_event(pipeline, gst_event_new_eos());
126 | sigint_restore();
127 | return;
128 | }
129 | catch (std::exception &e)
130 | {
131 | cerr << "An exception occurred in IntHandler(): " << endl << e.what() << endl;
132 | }
133 | }
134 |
135 | // ******* END variables, call-backs, etc. for use with gstreamer ********
136 |
137 |
138 | gint main(gint argc, gchar *argv[])
139 | {
140 | try
141 | {
142 | // signal handler for ctrl+C
143 | signal(SIGINT, IntHandler);
144 |
145 | cout << "Press CTRL+C at any time to quit." << endl;
146 |
147 | // initialize GStreamer
148 | gst_init(NULL, NULL);
149 |
150 | // create the mainloop
151 | loop = g_main_loop_new(NULL, FALSE);
152 |
153 | // The InstantCameraForAppSrc will manage the physical camera and pylon driver
154 | // and provide a source element to the GStreamer pipeline.
155 | CInstantCameraAppSrc camera1("21734321");
156 | CInstantCameraAppSrc camera2("21708961");
157 |
158 | // rescale both cameras' images to 320x240 for demo purposes
159 | int rescaleWidth = 320;
160 | int rescaleHeight = 240;
161 |
162 | // Initialize the cameras and driver for use with GStreamer
163 | // use maximum possible width and height, and maximum possible framerate under current settings.
164 | cout << "Initializing camera and driver..." << endl;
165 | camera1.InitCamera(-1, -1, -1, true, false, rescaleWidth, rescaleHeight);
166 | camera2.InitCamera(-1, -1, -1, true, false, rescaleWidth, rescaleHeight);
167 |
168 | // Apply some additional settings you may like
169 | cout << "Applying additional user settings..." << endl;
170 | // Set the same exposure time for both cameras
171 | GenApi::CEnumerationPtr(camera1.GetNodeMap().GetNode("ExposureAuto"))->FromString("Off");
172 | GenApi::CEnumerationPtr(camera2.GetNodeMap().GetNode("ExposureAuto"))->FromString("Off");
173 | GenApi::CFloatPtr(camera1.GetNodeMap().GetNode("ExposureTime"))->SetValue(3000);
174 | GenApi::CFloatPtr(camera2.GetNodeMap().GetNode("ExposureTime"))->SetValue(3000);
175 |
176 | // Split the bandwidth between both cameras. This is critical for multi-camera operation.
177 | // example: if we are using two usb cameras
178 | if (camera1.GetDeviceInfo().GetDeviceClass() == Pylon::BaslerUsbDeviceClass && camera1.GetDeviceInfo().GetDeviceClass() == Pylon::BaslerUsbDeviceClass)
179 | {
180 | // Turn on the bandwidth limiter
181 | GenApi::CEnumerationPtr(camera1.GetNodeMap().GetNode("DeviceLinkThroughputLimitMode"))->FromString("On");
182 | GenApi::CEnumerationPtr(camera2.GetNodeMap().GetNode("DeviceLinkThroughputLimitMode"))->FromString("On");
183 |
184 | // Set each camera's limit to 150 MB/sec. Typically USB 3 can support ~350-400 MB/sec, but performance varies based on the host system's chipset.
185 | // So, assuming a maximum of 300 MB/sec per chipset is usually safe.
186 | GenApi::CIntegerPtr(camera1.GetNodeMap().GetNode("DeviceLinkThroughputLimit"))->SetValue(150000000);
187 | GenApi::CIntegerPtr(camera2.GetNodeMap().GetNode("DeviceLinkThroughputLimit"))->SetValue(150000000);
188 | }
189 |
190 | // If we change settings like exposuretime, bandwidth, width, height, etc.
191 | // Then the camera's framerate possibilities have probably changed...
192 | // Since we are using multiple cameras, we probably want them to be "in sync", so let's use the maximum common framerate between them
193 | double frameRateCamera1 = camera1.GetFrameRate(); // get the max framerate based on current settings
194 | double frameRateCamera2 = camera2.GetFrameRate();
195 | double maxCommonFrameRate = 0;
196 |
197 | if (frameRateCamera1 <= frameRateCamera2)
198 | maxCommonFrameRate = frameRateCamera1;
199 | else
200 | maxCommonFrameRate = frameRateCamera2;
201 |
202 | camera1.SetFrameRate(maxCommonFrameRate);
203 | camera2.SetFrameRate(maxCommonFrameRate);
204 |
205 | cout << "Maximum common framerate: " << maxCommonFrameRate << endl;
206 |
207 | cout << "Using Camera : " << camera1.GetDeviceInfo().GetFriendlyName() << endl;
208 | cout << "Camera Area Of Interest : " << camera1.GetWidth() << "x" << camera1.GetHeight() << endl;
209 | cout << "Camera Speed : " << camera1.GetFrameRate() << " fps" << endl;
210 | cout << endl;
211 | cout << "Using Camera : " << camera2.GetDeviceInfo().GetFriendlyName() << endl;
212 | cout << "Camera Area Of Interest : " << camera2.GetWidth() << "x" << camera2.GetHeight() << endl;
213 | cout << "Camera Speed : " << camera2.GetFrameRate() << " fps" << endl;
214 | cout << endl;
215 |
216 | cout << "Creating pipeline to display two cameras side-by-side..." << endl;
217 | cout << endl;
218 |
219 | // create a new pipeline to add elements too
220 | pipeline = gst_pipeline_new("pipeline");
221 |
222 | // prepare a handler (watcher) for messages from the pipeline
223 | bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));
224 | bus_watch_id = gst_bus_add_watch(bus, bus_call, loop);
225 | gst_object_unref(bus);
226 |
227 | // Create the other needed gstreamer pipeline elements
228 | GstElement *source1;
229 | GstElement *source2;
230 | GstElement *videoconvert1;
231 | GstElement *videoconvert2;
232 | GstElement *compositor;
233 | GstPad *compositor_sink_pad1;
234 | GstPad *compositor_sink_pad2;
235 | GstElement *capsfilter;
236 | GstElement *sink;
237 |
238 | // Use the cameras as the source of the pipeline.
239 | source1 = camera1.GetSource();
240 | source2 = camera2.GetSource();
241 |
242 | // some video format converters may be needed
243 | videoconvert1 = gst_element_factory_make("videoconvert", "videoconvert1");
244 | videoconvert2 = gst_element_factory_make("videoconvert", "videoconvert2");
245 |
246 | // The compositor element will take care for mixing the two camera streams into one window for display
247 | cout << "Creating compositor..." << endl;
248 | compositor = gst_element_factory_make("compositor", "compositor");
249 |
250 | // The compositor's sink pads will decide where to place the videos (eg: next to each other)
251 | GstPadTemplate* compositor_sink_pad_t = gst_element_class_get_pad_template(GST_ELEMENT_GET_CLASS(compositor), "sink_%u");
252 | compositor_sink_pad1 = gst_element_request_pad(compositor, compositor_sink_pad_t, NULL, NULL);
253 | compositor_sink_pad2 = gst_element_request_pad(compositor, compositor_sink_pad_t, NULL, NULL);
254 | g_object_set(compositor_sink_pad1, "xpos", 0, "ypos", 0, NULL);
255 | g_object_set(compositor_sink_pad2, "xpos", rescaleWidth, "ypos", 0, NULL);
256 |
257 | // The capsfilter element will tell the sink what framerate to support (if possible)
258 | capsfilter = gst_element_factory_make("capsfilter", "capsfilter");
259 | GstCaps *caps = gst_caps_new_simple("video/x-raw", "framerate", GST_TYPE_FRACTION, (int)maxCommonFrameRate, 1, NULL);
260 | g_object_set(G_OBJECT(capsfilter), "caps", caps, NULL);
261 | gst_caps_unref(caps);
262 |
263 | // The sink element for this sample will be whatever videosink the system prefers for display.
264 | sink = gst_element_factory_make("autovideosink", "videosink");
265 | g_object_set(sink, "sync", false, NULL);
266 | g_object_set(sink, "message-forward", true, NULL);
267 |
268 | // Add all the elements to the pipeline.
269 | gst_bin_add_many(GST_BIN(pipeline), source1, videoconvert1, compositor, sink, source2, videoconvert2, capsfilter, NULL);
270 |
271 | // Link the elements together
272 | gst_element_link_many(source1, videoconvert1, compositor, capsfilter, sink, NULL);
273 | gst_element_link_many(source2, videoconvert2, compositor, capsfilter, sink, NULL);
274 | gst_element_link_many(compositor, sink, NULL);
275 |
276 | // Start the camera and grab engine.
277 | if (camera1.StartCamera() == false || camera2.StartCamera() == false)
278 | {
279 | exitCode = -1;
280 | throw std::runtime_error("Could not start camera!");
281 | }
282 |
283 | // Start the pipeline.
284 | cout << "Starting pipeline..." << endl;
285 | gst_element_set_state(pipeline, GST_STATE_PLAYING);
286 |
287 | // run the main loop. When Ctrl+C is pressed, an EOS event will be sent
288 | // which will shutdown the pipeline in intHandler(), which will in turn quit the main loop.
289 | g_main_loop_run(loop);
290 |
291 | // clean up
292 | cout << "Stopping pipeline..." << endl;
293 | gst_element_set_state(pipeline, GST_STATE_NULL);
294 |
295 | camera1.StopCamera();
296 | camera1.CloseCamera();
297 |
298 | camera2.StopCamera();
299 | camera2.CloseCamera();
300 |
301 | gst_object_unref(GST_OBJECT(pipeline));
302 | g_main_loop_unref(loop);
303 |
304 | exitCode = 0;
305 |
306 | }
307 | catch (GenICam::GenericException &e)
308 | {
309 | cerr << "An exception occured in main(): " << endl << e.GetDescription() << endl;
310 | exitCode = -1;
311 | }
312 | catch (std::exception &e)
313 | {
314 | cerr << "An exception occurred in main(): " << endl << e.what() << endl;
315 | exitCode = -1;
316 | }
317 |
318 | // Comment the following two lines to disable waiting on exit.
319 | cerr << endl << "Press Enter to exit." << endl;
320 | while (cin.get() != '\n');
321 |
322 | return exitCode;
323 | }
324 |
--------------------------------------------------------------------------------
/Samples/demopylongstreamer/CPipelineHelper.cpp:
--------------------------------------------------------------------------------
1 | /* CPipelineHelper.cpp: Definition file for CPipelineHeader Class.
2 | Given a GStreamer pipeline and source, this will finish building a pipeline.
3 |
4 | Copyright 2017-2019 Matthew Breit
5 |
6 | Licensed under the Apache License, Version 2.0 (the "License");
7 | you may not use this file except in compliance with the License.
8 | You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing, software
13 | distributed under the License is distributed on an "AS IS" BASIS,
14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | See the License for the specific language governing permissions and
16 | limitations under the License.
17 |
18 | THIS SOFTWARE REQUIRES ADDITIONAL SOFTWARE (IE: LIBRARIES) IN ORDER TO COMPILE
19 | INTO BINARY FORM AND TO FUNCTION IN BINARY FORM. ANY SUCH ADDITIONAL SOFTWARE
20 | IS OUTSIDE THE SCOPE OF THIS LICENSE.
21 | */
22 |
23 | #include "CPipelineHelper.h"
24 |
25 | #include
26 | #include
27 |
28 | using namespace std;
29 |
30 | // ****************************************************************************
31 | // For Debugging, the functions below can print the caps of elements
32 | // These come from GStreamer Documentation.
33 | // They are defined at the end of this file.
34 | // example usage:
35 | // print_pad_capabilities(convert, "src");
36 | // print_pad_capabilities(encoder, "sink");
37 |
38 | static gboolean print_field (GQuark field, const GValue * value, gpointer pfx);
39 | static void print_caps (const GstCaps * caps, const gchar * pfx);
40 | static void print_pad_templates_information (GstElementFactory * factory);
41 | static void print_pad_capabilities (GstElement *element, gchar *pad_name);
42 | // ****************************************************************************
43 |
44 | CPipelineHelper::CPipelineHelper(GstElement *pipeline, GstElement *source)
45 | {
46 | m_pipelineBuilt = false;
47 | m_pipeline = pipeline;
48 | m_source = source;
49 | }
50 |
51 | CPipelineHelper::~CPipelineHelper()
52 | {
53 | }
54 |
55 | // example of how to create a pipeline for display in a window
56 | bool CPipelineHelper::build_pipeline_display()
57 | {
58 | try
59 | {
60 | if (m_pipelineBuilt == true)
61 | {
62 | cout << "Cancelling -display. Another pipeline has already been built." << endl;
63 | return false;
64 | }
65 |
66 |
67 | GstElement *convert;
68 | GstElement *sink;
69 |
70 | cout << "Creating Pipeline for displaying images in local window..." << endl;
71 | // Create gstreamer elements
72 | convert = gst_element_factory_make("videoconvert", "converter");
73 | sink = gst_element_factory_make("autovideosink", "videosink"); // depending on your platform, you may have to use some alternative here, like ("autovideosink", "sink")
74 |
75 | if (!convert){ cout << "Could not make convert" << endl; return false; }
76 | if (!sink){ cout << "Could not make sink" << endl; return false; }
77 |
78 | // if you are using nvidia tx1/tx2, the built-in video sink that is found by autovideosink does not advertise it needs conversion (it does not support RGB).
79 | // so we must use a filter such that the converter knows to convert the image format.
80 | // if you are using a video sink that supports RGB, then you do not need to convert to i420 and you can remove this filter and save some cpu load.
81 | GstElement *filter;
82 | GstCaps *filter_caps;
83 | filter = gst_element_factory_make("capsfilter", "filter");
84 | filter_caps = gst_caps_new_simple("video/x-raw",
85 | "format", G_TYPE_STRING, "I420",
86 | NULL);
87 |
88 | g_object_set(G_OBJECT(filter), "caps", filter_caps, NULL);
89 | gst_caps_unref(filter_caps);
90 |
91 | // add and link the pipeline elements
92 | gst_bin_add_many(GST_BIN(m_pipeline), m_source, convert, filter, sink, NULL);
93 | gst_element_link_many(m_source, convert, filter, sink, NULL);
94 |
95 |
96 | cout << "Pipeline Made." << endl;
97 |
98 | m_pipelineBuilt = true;
99 |
100 | return true;
101 | }
102 | catch (std::exception &e)
103 | {
104 | cerr << "An exception occurred in build_pipeline_display(): " << endl << e.what() << endl;
105 | return false;
106 | }
107 | }
108 |
109 | // example of how to create a pipeline for piping images to a linux framebuffer
110 | bool CPipelineHelper::build_pipeline_framebuffer(string fbDevice)
111 | {
112 | try
113 | {
114 | if (m_pipelineBuilt == true)
115 | {
116 | cout << "Cancelling -framebuffer. Another pipeline has already been built." << endl;
117 | return false;
118 | }
119 |
120 | GstElement *convert;
121 | GstElement *sink;
122 |
123 | cout << "Creating Pipeline for sending images to framebuffer " << fbDevice << "..." << endl;
124 |
125 | /* Create gstreamer elements */
126 | convert = gst_element_factory_make("videoconvert", "converter");
127 | sink = gst_element_factory_make("fbdevsink", "fbsink");
128 |
129 | if (!convert){ cout << "Could not make convert" << endl; return false; }
130 | if (!sink){ cout << "Could not make sink" << endl; return false; }
131 |
132 | g_object_set(G_OBJECT(sink), "device", fbDevice.c_str(), NULL);
133 |
134 | // add and link the pipeline elements
135 | gst_bin_add_many(GST_BIN(m_pipeline), m_source, convert, sink, NULL);
136 | gst_element_link_many(m_source, convert, sink, NULL);
137 |
138 | cout << "Pipeline Made." << endl;
139 |
140 | m_pipelineBuilt = true;
141 |
142 | return true;
143 | }
144 | catch (std::exception &e)
145 | {
146 | cerr << "An exception occurred in build_pipeline_framebuffer(): " << endl << e.what() << endl;
147 | return false;
148 | }
149 | }
150 |
151 | // example of how to create a pipeline for encoding images in h264 format and streaming across a network
152 | bool CPipelineHelper::build_pipeline_h264stream(string ipAddress)
153 | {
154 | try
155 | {
156 | if (m_pipelineBuilt == true)
157 | {
158 | cout << "Cancelling -h264stream. Another pipeline has already been built." << endl;
159 | return false;
160 | }
161 |
162 | GstElement *convert;
163 | GstElement *encoder;
164 | GstElement *filter2;
165 | GstElement *rtp264;
166 | GstElement *sink;
167 | GstCaps *filter2_caps;
168 | int port = 554;
169 |
170 | cout << "Creating Pipeline for streaming images as h264 video across network to: " << ipAddress << ":" << port << "..." << endl;
171 | cout << "Start the receiver PC first with this command: " << endl;
172 | cout << "gst-launch-1.0 udpsrc port=" << port << " ! application/x-rtp,encoding-name=H264,payload=96 ! rtph264depay ! avdec_h264 ! autovideosink sync=false async=false -e" << endl;
173 | cout << "Then press enter to continue..." << endl;
174 | cin.get();
175 |
176 | // Create gstreamer elements
177 | convert = gst_element_factory_make("videoconvert", "converter");
178 |
179 | // depending on your platform, you may have to use some alternative encoder here.
180 | cout << "Trying omxh264enc encoder..." << endl;
181 | encoder = gst_element_factory_make("omxh264enc", "omxh264enc"); // omxh264enc works good on Raspberry Pi and Jetson Nano
182 | if (!encoder)
183 | {
184 | cout << "Could not make omxh264enc encoder. Trying imxvpuenc_h264..." << endl;
185 | encoder = gst_element_factory_make("imxvpuenc_h264", "imxvpuenc_h264"); // for i.MX devices.
186 | if (!encoder)
187 | {
188 | cout << "Could not make imxvpuenc_h264 encoder. Trying v4l2h264enc..." << endl;
189 | encoder = gst_element_factory_make("v4l2h264enc", "v4l2h264enc"); // for Snapdragon 820 devices
190 | if (!encoder)
191 | {
192 | cout << "Could not make v4l2h264enc encoder. Trying x264enc..." << endl;
193 | encoder = gst_element_factory_make("x264enc", "x264enc"); // for other devices
194 | if (!encoder)
195 | {
196 | cout << "Could not make x264enc encoder. Giving up..." << endl;
197 | return false; // give up
198 | }
199 | }
200 | }
201 | }
202 | filter2 = gst_element_factory_make("capsfilter", "filter2");
203 | rtp264 = gst_element_factory_make("rtph264pay", "rtp264");
204 | sink = gst_element_factory_make("udpsink", "udpsink");
205 |
206 | if (!convert){ cout << "Could not make convert" << endl; return false; }
207 | if (!filter2){ cout << "Could not make filter2" << endl; return false; }
208 | if (!rtp264){ cout << "Could not make rtp264" << endl; return false; }
209 | if (!sink){ cout << "Could not make sink" << endl; return false; }
210 |
211 | // specify some settings on the elements
212 | // Different encoders have different features you can set.
213 | if (encoder->object.name == "x264enc")
214 | {
215 | // for compatibility on resource-limited systems, set the encoding preset "ultrafast". Lowest quality video, but lowest lag.
216 | g_object_set(G_OBJECT(encoder), "speed-preset", 1, NULL);
217 | }
218 |
219 | if (encoder->object.name == "omxh264enc")
220 | {
221 | // 1 = baseline, 2 = main, 3 = high
222 | g_object_set(G_OBJECT(encoder), "profile", 8, NULL);
223 |
224 | }
225 |
226 | // filter2 capabilities
227 | filter2_caps = gst_caps_new_simple("video/x-h264",
228 | "stream-format", G_TYPE_STRING, "byte-stream",
229 | NULL);
230 |
231 | g_object_set(G_OBJECT(filter2), "caps", filter2_caps, NULL);
232 | gst_caps_unref(filter2_caps);
233 |
234 | // sink
235 | g_object_set(G_OBJECT(sink), "host", ipAddress.c_str(), "port", port, "sync", FALSE, "async", FALSE, NULL);
236 |
237 | // add and link the pipeline elements
238 | gst_bin_add_many(GST_BIN(m_pipeline), m_source, convert, encoder, filter2, rtp264, sink, NULL);
239 | gst_element_link_many(m_source, convert, encoder, filter2, rtp264, sink, NULL);
240 |
241 | cout << "Pipeline Made." << endl;
242 |
243 | m_pipelineBuilt = true;
244 |
245 | return true;
246 | }
247 | catch (std::exception &e)
248 | {
249 | cerr << "An exception occurred in build_pipeline_h264stream(): " << endl << e.what() << endl;
250 | return false;
251 | }
252 |
253 | }
254 |
255 | // example of how to create a pipeline for encoding images in h264 format and streaming across a network
256 | bool CPipelineHelper::build_pipeline_h264multicast(string ipAddress)
257 | {
258 | try
259 | {
260 | if (m_pipelineBuilt == true)
261 | {
262 | cout << "Cancelling -h264stream. Another pipeline has already been built." << endl;
263 | return false;
264 | }
265 |
266 | GstElement *convert;
267 | GstElement *encoder;
268 | GstElement *filter2;
269 | GstElement *rtp264;
270 | GstElement *sink;
271 | GstCaps *filter2_caps;
272 | int port = 3500;
273 |
274 | cout << "Creating Pipeline for multicast streaming images as h264 video across network to group: " << ipAddress << ":" << port << "..." << endl;
275 | cout << "Start the receiver PC first with this command: " << endl;
276 | cout << "gst-launch-1.0 udpsrc multicast-group=" << ipAddress << " auto-multicast=true port=" << port << " ! application/x-rtp,encoding-name=H264,payload=96 ! rtph264depay ! avdec_h264 ! autovideosink sync=false async=false -e" << endl;
277 | cout << "Then press enter to continue..." << endl;
278 | cin.get();
279 |
280 | // Create gstreamer elements
281 | convert = gst_element_factory_make("videoconvert", "converter");
282 |
283 | // depending on your platform, you may have to use some alternative encoder here.
284 | cout << "Trying omxh264enc encoder..." << endl;
285 | encoder = gst_element_factory_make("omxh264enc", "omxh264enc"); // omxh264enc works good on Raspberry Pi and Jetson Nano
286 | if (!encoder)
287 | {
288 | cout << "Could not make omxh264enc encoder. Trying imxvpuenc_h264..." << endl;
289 | encoder = gst_element_factory_make("imxvpuenc_h264", "imxvpuenc_h264"); // for i.MX devices.
290 | if (!encoder)
291 | {
292 | cout << "Could not make imxvpuenc_h264 encoder. Trying v4l2h264enc..." << endl;
293 | encoder = gst_element_factory_make("v4l2h264enc", "v4l2h264enc"); // for Snapdragon 820 devices
294 | if (!encoder)
295 | {
296 | cout << "Could not make v4l2h264enc encoder. Trying x264enc..." << endl;
297 | encoder = gst_element_factory_make("x264enc", "x264enc"); // for other devices
298 | if (!encoder)
299 | {
300 | cout << "Could not make x264enc encoder. Giving up..." << endl;
301 | return false; // give up
302 | }
303 | }
304 | }
305 | }
306 | filter2 = gst_element_factory_make("capsfilter", "filter2");
307 | rtp264 = gst_element_factory_make("rtph264pay", "rtp264");
308 | sink = gst_element_factory_make("udpsink", "udpsink");
309 |
310 | if (!convert){ cout << "Could not make convert" << endl; return false; }
311 | if (!filter2){ cout << "Could not make filter2" << endl; return false; }
312 | if (!rtp264){ cout << "Could not make rtp264" << endl; return false; }
313 | if (!sink){ cout << "Could not make sink" << endl; return false; }
314 |
315 | // specify some settings on the elements
316 | // Different encoders have different features you can set.
317 | if (encoder->object.name == "x264enc")
318 | {
319 | // for compatibility on resource-limited systems, set the encoding preset "ultrafast". Lowest quality video, but lowest lag.
320 | g_object_set(G_OBJECT(encoder), "speed-preset", 1, NULL);
321 | }
322 |
323 | if (encoder->object.name == "omxh264enc")
324 | {
325 | // 1 = baseline, 2 = main, 3 = high
326 | g_object_set(G_OBJECT(encoder), "profile", 8, NULL);
327 |
328 | }
329 |
330 | // filter2 capabilities
331 | filter2_caps = gst_caps_new_simple("video/x-h264",
332 | "stream-format", G_TYPE_STRING, "byte-stream",
333 | NULL);
334 |
335 | g_object_set(G_OBJECT(filter2), "caps", filter2_caps, NULL);
336 | gst_caps_unref(filter2_caps);
337 |
338 | // sink
339 | g_object_set(G_OBJECT(sink), "host", ipAddress.c_str(), "port", port, "sync", FALSE, "async", FALSE, "auto-multicast", TRUE, NULL);
340 |
341 | // add and link the pipeline elements
342 | gst_bin_add_many(GST_BIN(m_pipeline), m_source, convert, encoder, filter2, rtp264, sink, NULL);
343 | gst_element_link_many(m_source, convert, encoder, filter2, rtp264, sink, NULL);
344 |
345 | cout << "Pipeline Made." << endl;
346 |
347 | m_pipelineBuilt = true;
348 |
349 | return true;
350 | }
351 | catch (std::exception &e)
352 | {
353 | cerr << "An exception occurred in build_pipeline_h264stream(): " << endl << e.what() << endl;
354 | return false;
355 | }
356 |
357 | }
358 |
359 | // example of how to create a pipeline for encoding images in h264 format and streaming to local video file
360 | bool CPipelineHelper::build_pipeline_h264file(string fileName)
361 | {
362 | try
363 | {
364 | if (m_pipelineBuilt == true)
365 | {
366 | cout << "Cancelling -h264file. Another pipeline has already been built." << endl;
367 | return false;
368 | }
369 |
370 | GstElement *convert;
371 | GstElement *encoder;
372 | GstElement *sink;
373 |
374 | cout << "Creating Pipeline for saving images as h264 video on local host: " << fileName << "..." << endl;
375 |
376 | // Create gstreamer elements
377 | convert = gst_element_factory_make("videoconvert", "converter");
378 |
379 | // depending on your platform, you may have to use some alternative encoder here.
380 | encoder = gst_element_factory_make("omxh264enc", "omxh264enc"); // omxh264enc works good on Raspberry Pi
381 | if (!encoder)
382 | {
383 | cout << "Could not make omxh264enc encoder. Trying imxvpuenc_h264..." << endl;
384 | encoder = gst_element_factory_make("imxvpuenc_h264", "imxvpuenc_h264"); // for i.MX devices.
385 | if (!encoder)
386 | {
387 | cout << "Could not make imxvpuenc_h264 encoder. Trying x264enc..." << endl;
388 | encoder = gst_element_factory_make("x264enc", "x264enc"); // for other devices
389 | if (!encoder)
390 | {
391 | cout << "Could not make x264enc encoder." << endl;
392 | return false;
393 | }
394 | }
395 | }
396 | sink = gst_element_factory_make("filesink", "filesink");
397 |
398 |
399 | if (!convert){ cout << "Could not make convert" << endl; return false; }
400 | if (!encoder){ cout << "Could not make encoder" << endl; return false; }
401 | if (!sink){ cout << "Could not make sink" << endl; return false; }
402 |
403 | // Set up elements
404 |
405 | // Different encoders have different features you can set.
406 | if (encoder->object.name == "x264enc")
407 | {
408 | // for compatibility on resource-limited systems, set the encoding preset "ultrafast". Lowest quality video, but lowest lag.
409 | g_object_set(G_OBJECT(encoder), "speed-preset", 1, NULL);
410 | }
411 |
412 | g_object_set(G_OBJECT(sink), "location", fileName.c_str(), NULL);
413 |
414 | // add and link the pipeline elements
415 | gst_bin_add_many(GST_BIN(m_pipeline), m_source, convert, encoder, sink, NULL);
416 | gst_element_link_many(m_source, convert, encoder, sink, NULL);
417 |
418 | cout << "Pipeline Made." << endl;
419 |
420 | m_pipelineBuilt = true;
421 |
422 | return true;
423 | }
424 | catch (std::exception &e)
425 | {
426 | cerr << "An exception occurred in build_pipeline_h264file(): " << endl << e.what() << endl;
427 | return false;
428 | }
429 | }
430 |
431 | // example of how to create a pipeline from a string that you would use with gst-launch-1.0
432 | bool CPipelineHelper::build_pipeline_parsestring(string pipelineString)
433 | {
434 | try
435 | {
436 | if (m_pipelineBuilt == true)
437 | {
438 | cout << "Cancelling -parsestring. Another pipeline has already been built." << endl;
439 | return false;
440 | }
441 |
442 | cout << "Applying this Pipeline to the CInstantCameraAppsc: " << pipelineString << "..." << endl;
443 |
444 | string strPipeline = "";
445 | if (pipelineString.find("gst-launch") != std::string::npos)
446 | {
447 | std::size_t start = pipelineString.find("!");
448 | strPipeline = pipelineString.substr(start);
449 | }
450 | else
451 | strPipeline = pipelineString;
452 |
453 | GstElement *userPipeline;
454 | userPipeline = gst_parse_bin_from_description(strPipeline.c_str(), true, NULL);
455 |
456 | // add and link the pipeline elements
457 | gst_bin_add_many(GST_BIN(m_pipeline), m_source, userPipeline, NULL);
458 | gst_element_link_many(m_source, userPipeline, NULL);
459 |
460 | cout << "Pipeline Made." << endl;
461 |
462 | m_pipelineBuilt = true;
463 |
464 | return true;
465 | }
466 | catch (std::exception &e)
467 | {
468 | cerr << "An exception occurred in build_pipeline_parsestring(): " << endl << e.what() << endl;
469 | return false;
470 | }
471 | }
472 |
473 |
474 | // ****************************************************************************
475 | // debugging functions
476 |
477 | static gboolean print_field (GQuark field, const GValue * value, gpointer pfx) {
478 | gchar *str = gst_value_serialize (value);
479 |
480 | g_print ("%s %15s: %s\n", (gchar *) pfx, g_quark_to_string (field), str);
481 | g_free (str);
482 | return TRUE;
483 | }
484 |
485 | static void print_caps (const GstCaps * caps, const gchar * pfx) {
486 | guint i;
487 |
488 | g_return_if_fail (caps != NULL);
489 |
490 | if (gst_caps_is_any (caps)) {
491 | g_print ("%sANY\n", pfx);
492 | return;
493 | }
494 | if (gst_caps_is_empty (caps)) {
495 | g_print ("%sEMPTY\n", pfx);
496 | return;
497 | }
498 |
499 | for (i = 0; i < gst_caps_get_size (caps); i++) {
500 | GstStructure *structure = gst_caps_get_structure (caps, i);
501 |
502 | g_print ("%s%s\n", pfx, gst_structure_get_name (structure));
503 | gst_structure_foreach (structure, print_field, (gpointer) pfx);
504 | }
505 | }
506 |
507 | /* Prints information about a Pad Template, including its Capabilities */
508 | static void print_pad_templates_information (GstElementFactory * factory) {
509 | const GList *pads;
510 | GstStaticPadTemplate *padtemplate;
511 |
512 | g_print ("Pad Templates for %s:\n", gst_element_factory_get_longname (factory));
513 | if (!gst_element_factory_get_num_pad_templates (factory)) {
514 | g_print (" none\n");
515 | return;
516 | }
517 |
518 | pads = gst_element_factory_get_static_pad_templates (factory);
519 | while (pads) {
520 | padtemplate = (GstStaticPadTemplate*)pads->data;
521 | pads = g_list_next (pads);
522 |
523 | if (padtemplate->direction == GST_PAD_SRC)
524 | g_print (" SRC template: '%s'\n", padtemplate->name_template);
525 | else if (padtemplate->direction == GST_PAD_SINK)
526 | g_print (" SINK template: '%s'\n", padtemplate->name_template);
527 | else
528 | g_print (" UNKNOWN!!! template: '%s'\n", padtemplate->name_template);
529 |
530 | if (padtemplate->presence == GST_PAD_ALWAYS)
531 | g_print (" Availability: Always\n");
532 | else if (padtemplate->presence == GST_PAD_SOMETIMES)
533 | g_print (" Availability: Sometimes\n");
534 | else if (padtemplate->presence == GST_PAD_REQUEST)
535 | g_print (" Availability: On request\n");
536 | else
537 | g_print (" Availability: UNKNOWN!!!\n");
538 |
539 | if (padtemplate->static_caps.string) {
540 | GstCaps *caps;
541 | g_print (" Capabilities:\n");
542 | caps = gst_static_caps_get (&padtemplate->static_caps);
543 | print_caps (caps, " ");
544 | gst_caps_unref (caps);
545 |
546 | }
547 |
548 | g_print ("\n");
549 | }
550 | }
551 |
552 | /* Shows the CURRENT capabilities of the requested pad in the given element */
553 | static void print_pad_capabilities (GstElement *element, gchar *pad_name) {
554 | GstPad *pad = NULL;
555 | GstCaps *caps = NULL;
556 |
557 | /* Retrieve pad */
558 | pad = gst_element_get_static_pad (element, pad_name);
559 | if (!pad) {
560 | g_printerr ("Could not retrieve pad '%s'\n", pad_name);
561 | return;
562 | }
563 |
564 | /* Retrieve negotiated caps (or acceptable caps if negotiation is not finished yet) */
565 | caps = gst_pad_get_current_caps (pad);
566 | if (!caps)
567 | caps = gst_pad_query_caps (pad, NULL);
568 |
569 | /* Print and free */
570 | g_print ("Caps for the %s pad:\n", pad_name);
571 | print_caps (caps, " ");
572 | gst_caps_unref (caps);
573 | gst_object_unref (pad);
574 | }
575 | // ****************************************************************************
--------------------------------------------------------------------------------
/Samples/demopylongstreamer_jetson_performance/CPipelineHelper.cpp:
--------------------------------------------------------------------------------
1 | /* CPipelineHelper.cpp: Definition file for CPipelineHeader Class.
2 | Given a GStreamer pipeline and source, this will finish building a pipeline.
3 |
4 | Copyright 2017-2019 Matthew Breit
5 |
6 | Licensed under the Apache License, Version 2.0 (the "License");
7 | you may not use this file except in compliance with the License.
8 | You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing, software
13 | distributed under the License is distributed on an "AS IS" BASIS,
14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | See the License for the specific language governing permissions and
16 | limitations under the License.
17 |
18 | THIS SOFTWARE REQUIRES ADDITIONAL SOFTWARE (IE: LIBRARIES) IN ORDER TO COMPILE
19 | INTO BINARY FORM AND TO FUNCTION IN BINARY FORM. ANY SUCH ADDITIONAL SOFTWARE
20 | IS OUTSIDE THE SCOPE OF THIS LICENSE.
21 | */
22 |
23 | #include "CPipelineHelper.h"
24 |
25 | #include
26 | #include
27 |
28 | using namespace std;
29 |
30 | // ****************************************************************************
31 | // For Debugging, the functions below can print the caps of elements
32 | // These come from GStreamer Documentation.
33 | // They are defined at the end of this file.
34 | // example usage:
35 | // print_pad_capabilities(convert, "src");
36 | // print_pad_capabilities(encoder, "sink");
37 |
38 | static gboolean print_field (GQuark field, const GValue * value, gpointer pfx);
39 | static void print_caps (const GstCaps * caps, const gchar * pfx);
40 | static void print_pad_templates_information (GstElementFactory * factory);
41 | static void print_pad_capabilities (GstElement *element, gchar *pad_name);
42 | // ****************************************************************************
43 |
44 | CPipelineHelper::CPipelineHelper(GstElement *pipeline, GstElement *source)
45 | {
46 | m_pipelineBuilt = false;
47 | m_pipeline = pipeline;
48 | m_source = source;
49 | }
50 |
51 | CPipelineHelper::~CPipelineHelper()
52 | {
53 | }
54 |
55 | // example of how to create a pipeline for display in a window
56 | bool CPipelineHelper::build_pipeline_display()
57 | {
58 | try
59 | {
60 | if (m_pipelineBuilt == true)
61 | {
62 | cout << "Cancelling -display. Another pipeline has already been built." << endl;
63 | return false;
64 | }
65 |
66 |
67 | GstElement *convert;
68 | GstElement *sink;
69 |
70 | cout << "Creating Pipeline for displaying images in local window..." << endl;
71 | // Create gstreamer elements
72 | convert = gst_element_factory_make("videoconvert", "converter");
73 | sink = gst_element_factory_make("nv3dsink", "videosink"); // depending on your platform, you may have to use some alternative here, like ("autovideosink", "sink")
74 |
75 | if (!convert){ cout << "Could not make convert" << endl; return false; }
76 | if (!sink){ cout << "Could not make sink" << endl; return false; }
77 |
78 | // if you are using nvidia tx1/tx2, the built-in video sink that is found by autovideosink does not advertise it needs conversion (it does not support RGB).
79 | // so we must use a filter such that the converter knows to convert the image format.
80 | // if you are using a video sink that supports RGB, then you do not need to convert to i420 and you can remove this filter and save some cpu load.
81 | GstElement *filter;
82 | GstCaps *filter_caps;
83 | filter = gst_element_factory_make("capsfilter", "filter");
84 | filter_caps = gst_caps_new_simple("video/x-raw",
85 | "format", G_TYPE_STRING, "I420",
86 | NULL);
87 |
88 | g_object_set(G_OBJECT(filter), "caps", filter_caps, NULL);
89 | gst_caps_unref(filter_caps);
90 |
91 | // add and link the pipeline elements
92 | gst_bin_add_many(GST_BIN(m_pipeline), m_source, convert, filter, sink, NULL);
93 | gst_element_link_many(m_source, convert, filter, sink, NULL);
94 |
95 |
96 | cout << "Pipeline Made." << endl;
97 |
98 | m_pipelineBuilt = true;
99 |
100 | return true;
101 | }
102 | catch (std::exception &e)
103 | {
104 | cerr << "An exception occurred in build_pipeline_display(): " << endl << e.what() << endl;
105 | return false;
106 | }
107 | }
108 |
109 | // example of how to create a pipeline for piping images to a linux framebuffer
110 | bool CPipelineHelper::build_pipeline_framebuffer(string fbDevice)
111 | {
112 | try
113 | {
114 | if (m_pipelineBuilt == true)
115 | {
116 | cout << "Cancelling -framebuffer. Another pipeline has already been built." << endl;
117 | return false;
118 | }
119 |
120 | GstElement *convert;
121 | GstElement *sink;
122 |
123 | cout << "Creating Pipeline for sending images to framebuffer " << fbDevice << "..." << endl;
124 |
125 | /* Create gstreamer elements */
126 | convert = gst_element_factory_make("videoconvert", "converter");
127 | sink = gst_element_factory_make("fbdevsink", "fbsink");
128 |
129 | if (!convert){ cout << "Could not make convert" << endl; return false; }
130 | if (!sink){ cout << "Could not make sink" << endl; return false; }
131 |
132 | g_object_set(G_OBJECT(sink), "device", fbDevice.c_str(), NULL);
133 |
134 | // add and link the pipeline elements
135 | gst_bin_add_many(GST_BIN(m_pipeline), m_source, convert, sink, NULL);
136 | gst_element_link_many(m_source, convert, sink, NULL);
137 |
138 | cout << "Pipeline Made." << endl;
139 |
140 | m_pipelineBuilt = true;
141 |
142 | return true;
143 | }
144 | catch (std::exception &e)
145 | {
146 | cerr << "An exception occurred in build_pipeline_framebuffer(): " << endl << e.what() << endl;
147 | return false;
148 | }
149 | }
150 |
151 | // example of how to create a pipeline for encoding images in h264 format and streaming across a network
152 | bool CPipelineHelper::build_pipeline_h264stream(string ipAddress)
153 | {
154 | try
155 | {
156 | if (m_pipelineBuilt == true)
157 | {
158 | cout << "Cancelling -h264stream. Another pipeline has already been built." << endl;
159 | return false;
160 | }
161 |
162 | GstElement *convert;
163 | GstElement *encoder;
164 | GstElement *filter2;
165 | GstElement *rtp264;
166 | GstElement *sink;
167 | GstCaps *filter2_caps;
168 | int port = 554;
169 |
170 | cout << "Creating Pipeline for streaming images as h264 video across network to: " << ipAddress << ":" << port << "..." << endl;
171 | cout << "Start the receiver PC first with this command: " << endl;
172 | cout << "gst-launch-1.0 udpsrc port=" << port << " ! application/x-rtp,encoding-name=H264,payload=96 ! rtph264depay ! avdec_h264 ! autovideosink sync=false async=false -e" << endl;
173 | cout << "Then press enter to continue..." << endl;
174 | cin.get();
175 |
176 | // Create gstreamer elements
177 | convert = gst_element_factory_make("videoconvert", "converter");
178 |
179 | // depending on your platform, you may have to use some alternative encoder here.
180 | cout << "Trying omxh264enc encoder..." << endl;
181 | encoder = gst_element_factory_make("omxh264enc", "omxh264enc"); // omxh264enc works good on Raspberry Pi and Jetson Nano
182 | if (!encoder)
183 | {
184 | cout << "Could not make omxh264enc encoder. Trying imxvpuenc_h264..." << endl;
185 | encoder = gst_element_factory_make("imxvpuenc_h264", "imxvpuenc_h264"); // for i.MX devices.
186 | if (!encoder)
187 | {
188 | cout << "Could not make imxvpuenc_h264 encoder. Trying v4l2h264enc..." << endl;
189 | encoder = gst_element_factory_make("v4l2h264enc", "v4l2h264enc"); // for Snapdragon 820 devices
190 | if (!encoder)
191 | {
192 | cout << "Could not make v4l2h264enc encoder. Trying x264enc..." << endl;
193 | encoder = gst_element_factory_make("x264enc", "x264enc"); // for other devices
194 | if (!encoder)
195 | {
196 | cout << "Could not make x264enc encoder. Giving up..." << endl;
197 | return false; // give up
198 | }
199 | }
200 | }
201 | }
202 | filter2 = gst_element_factory_make("capsfilter", "filter2");
203 | rtp264 = gst_element_factory_make("rtph264pay", "rtp264");
204 | sink = gst_element_factory_make("udpsink", "udpsink");
205 |
206 | if (!convert){ cout << "Could not make convert" << endl; return false; }
207 | if (!filter2){ cout << "Could not make filter2" << endl; return false; }
208 | if (!rtp264){ cout << "Could not make rtp264" << endl; return false; }
209 | if (!sink){ cout << "Could not make sink" << endl; return false; }
210 |
211 | // specify some settings on the elements
212 | // Different encoders have different features you can set.
213 | if (encoder->object.name == "x264enc")
214 | {
215 | // for compatibility on resource-limited systems, set the encoding preset "ultrafast". Lowest quality video, but lowest lag.
216 | g_object_set(G_OBJECT(encoder), "speed-preset", 1, NULL);
217 | }
218 |
219 | if (encoder->object.name == "omxh264enc")
220 | {
221 | // 1 = baseline, 2 = main, 3 = high
222 | g_object_set(G_OBJECT(encoder), "profile", 8, NULL);
223 |
224 | }
225 |
226 | // filter2 capabilities
227 | filter2_caps = gst_caps_new_simple("video/x-h264",
228 | "stream-format", G_TYPE_STRING, "byte-stream",
229 | NULL);
230 |
231 | g_object_set(G_OBJECT(filter2), "caps", filter2_caps, NULL);
232 | gst_caps_unref(filter2_caps);
233 |
234 | // sink
235 | g_object_set(G_OBJECT(sink), "host", ipAddress.c_str(), "port", port, "sync", FALSE, "async", FALSE, NULL);
236 |
237 | // add and link the pipeline elements
238 | gst_bin_add_many(GST_BIN(m_pipeline), m_source, convert, encoder, filter2, rtp264, sink, NULL);
239 | gst_element_link_many(m_source, convert, encoder, filter2, rtp264, sink, NULL);
240 |
241 | cout << "Pipeline Made." << endl;
242 |
243 | m_pipelineBuilt = true;
244 |
245 | return true;
246 | }
247 | catch (std::exception &e)
248 | {
249 | cerr << "An exception occurred in build_pipeline_h264stream(): " << endl << e.what() << endl;
250 | return false;
251 | }
252 |
253 | }
254 |
255 | // example of how to create a pipeline for encoding images in h264 format and streaming across a network
256 | bool CPipelineHelper::build_pipeline_h264multicast(string ipAddress)
257 | {
258 | try
259 | {
260 | if (m_pipelineBuilt == true)
261 | {
262 | cout << "Cancelling -h264stream. Another pipeline has already been built." << endl;
263 | return false;
264 | }
265 |
266 | GstElement *convert;
267 | GstElement *encoder;
268 | GstElement *filter2;
269 | GstElement *rtp264;
270 | GstElement *sink;
271 | GstCaps *filter2_caps;
272 | int port = 3500;
273 |
274 | cout << "Creating Pipeline for multicast streaming images as h264 video across network to group: " << ipAddress << ":" << port << "..." << endl;
275 | cout << "Start the receiver PC first with this command: " << endl;
276 | cout << "gst-launch-1.0 udpsrc multicast-group=" << ipAddress << " auto-multicast=true port=" << port << " ! application/x-rtp,encoding-name=H264,payload=96 ! rtph264depay ! avdec_h264 ! autovideosink sync=false async=false -e" << endl;
277 | cout << "Then press enter to continue..." << endl;
278 | cin.get();
279 |
280 | // Create gstreamer elements
281 | convert = gst_element_factory_make("videoconvert", "converter");
282 |
283 | // depending on your platform, you may have to use some alternative encoder here.
284 | cout << "Trying omxh264enc encoder..." << endl;
285 | encoder = gst_element_factory_make("omxh264enc", "omxh264enc"); // omxh264enc works good on Raspberry Pi and Jetson Nano
286 | if (!encoder)
287 | {
288 | cout << "Could not make omxh264enc encoder. Trying imxvpuenc_h264..." << endl;
289 | encoder = gst_element_factory_make("imxvpuenc_h264", "imxvpuenc_h264"); // for i.MX devices.
290 | if (!encoder)
291 | {
292 | cout << "Could not make imxvpuenc_h264 encoder. Trying v4l2h264enc..." << endl;
293 | encoder = gst_element_factory_make("v4l2h264enc", "v4l2h264enc"); // for Snapdragon 820 devices
294 | if (!encoder)
295 | {
296 | cout << "Could not make v4l2h264enc encoder. Trying x264enc..." << endl;
297 | encoder = gst_element_factory_make("x264enc", "x264enc"); // for other devices
298 | if (!encoder)
299 | {
300 | cout << "Could not make x264enc encoder. Giving up..." << endl;
301 | return false; // give up
302 | }
303 | }
304 | }
305 | }
306 | filter2 = gst_element_factory_make("capsfilter", "filter2");
307 | rtp264 = gst_element_factory_make("rtph264pay", "rtp264");
308 | sink = gst_element_factory_make("udpsink", "udpsink");
309 |
310 | if (!convert){ cout << "Could not make convert" << endl; return false; }
311 | if (!filter2){ cout << "Could not make filter2" << endl; return false; }
312 | if (!rtp264){ cout << "Could not make rtp264" << endl; return false; }
313 | if (!sink){ cout << "Could not make sink" << endl; return false; }
314 |
315 | // specify some settings on the elements
316 | // Different encoders have different features you can set.
317 | if (encoder->object.name == "x264enc")
318 | {
319 | // for compatibility on resource-limited systems, set the encoding preset "ultrafast". Lowest quality video, but lowest lag.
320 | g_object_set(G_OBJECT(encoder), "speed-preset", 1, NULL);
321 | }
322 |
323 | if (encoder->object.name == "omxh264enc")
324 | {
325 | // 1 = baseline, 2 = main, 3 = high
326 | g_object_set(G_OBJECT(encoder), "profile", 8, NULL);
327 |
328 | }
329 |
330 | // filter2 capabilities
331 | filter2_caps = gst_caps_new_simple("video/x-h264",
332 | "stream-format", G_TYPE_STRING, "byte-stream",
333 | NULL);
334 |
335 | g_object_set(G_OBJECT(filter2), "caps", filter2_caps, NULL);
336 | gst_caps_unref(filter2_caps);
337 |
338 | // sink
339 | g_object_set(G_OBJECT(sink), "host", ipAddress.c_str(), "port", port, "sync", FALSE, "async", FALSE, "auto-multicast", TRUE, NULL);
340 |
341 | // add and link the pipeline elements
342 | gst_bin_add_many(GST_BIN(m_pipeline), m_source, convert, encoder, filter2, rtp264, sink, NULL);
343 | gst_element_link_many(m_source, convert, encoder, filter2, rtp264, sink, NULL);
344 |
345 | cout << "Pipeline Made." << endl;
346 |
347 | m_pipelineBuilt = true;
348 |
349 | return true;
350 | }
351 | catch (std::exception &e)
352 | {
353 | cerr << "An exception occurred in build_pipeline_h264stream(): " << endl << e.what() << endl;
354 | return false;
355 | }
356 |
357 | }
358 |
359 | // example of how to create a pipeline for encoding images in h264 format and streaming to local video file
360 | bool CPipelineHelper::build_pipeline_h264file(string fileName)
361 | {
362 | try
363 | {
364 | if (m_pipelineBuilt == true)
365 | {
366 | cout << "Cancelling -h264file. Another pipeline has already been built." << endl;
367 | return false;
368 | }
369 |
370 | GstElement *convert;
371 | GstElement *queue;
372 | GstElement *encoder;
373 | GstElement *h264parse;
374 | GstElement *mp4mux;
375 | GstElement *sink;
376 |
377 | cout << "Creating Pipeline for saving images as h264 video on local host: " << fileName << "..." << endl;
378 |
379 | // Create gstreamer elements
380 | convert = gst_element_factory_make("videoconvert", "converter");
381 |
382 | queue = gst_element_factory_make("queue","queue");
383 |
384 | // depending on your platform, you may have to use some alternative encoder here.
385 | encoder = gst_element_factory_make("omxh264enc", "omxh264enc"); // omxh264enc works good on Raspberry Pi
386 | if (!encoder)
387 | {
388 | cout << "Could not make omxh264enc encoder. Trying imxvpuenc_h264..." << endl;
389 | encoder = gst_element_factory_make("imxvpuenc_h264", "imxvpuenc_h264"); // for i.MX devices.
390 | if (!encoder)
391 | {
392 | cout << "Could not make imxvpuenc_h264 encoder. Trying x264enc..." << endl;
393 | encoder = gst_element_factory_make("x264enc", "x264enc"); // for other devices
394 | if (!encoder)
395 | {
396 | cout << "Could not make x264enc encoder." << endl;
397 | return false;
398 | }
399 | }
400 | }
401 | h264parse = gst_element_factory_make("h264parse", "h264parse");
402 | mp4mux = gst_element_factory_make("qtmux", "mp4mux");
403 | sink = gst_element_factory_make("filesink", "filesink");
404 |
405 |
406 | if (!convert){ cout << "Could not make convert" << endl; return false; }
407 | if (!queue){ cout << "Could not make queue" << endl; return false;}
408 | if (!encoder){ cout << "Could not make encoder" << endl; return false; }
409 | if (!h264parse){ cout << "Could not make h264parse" << endl; return false;}
410 | if (!mp4mux){ cout << "Could not make mp4mux" << endl; return false;}
411 | if (!sink){ cout << "Could not make sink" << endl; return false; }
412 |
413 | // Set up elements
414 |
415 | // Different encoders have different features you can set.
416 | if (encoder->object.name == "x264enc")
417 | {
418 | // for compatibility on resource-limited systems, set the encoding preset "ultrafast". Lowest quality video, but lowest lag.
419 | g_object_set(G_OBJECT(encoder), "speed-preset", 1, NULL);
420 | }
421 |
422 | g_object_set(G_OBJECT(sink), "location", fileName.c_str(), NULL);
423 |
424 | // add and link the pipeline elements
425 | gst_bin_add_many(GST_BIN(m_pipeline), m_source, convert, queue, encoder, h264parse, mp4mux, sink, NULL);
426 | gst_element_link_many(m_source, convert, queue, encoder, h264parse, mp4mux, sink, NULL);
427 |
428 | cout << "Pipeline Made." << endl;
429 |
430 | m_pipelineBuilt = true;
431 |
432 | return true;
433 | }
434 | catch (std::exception &e)
435 | {
436 | cerr << "An exception occurred in build_pipeline_h264file(): " << endl << e.what() << endl;
437 | return false;
438 | }
439 | }
440 |
441 | // example of how to create a pipeline from a string that you would use with gst-launch-1.0
442 | bool CPipelineHelper::build_pipeline_parsestring(string pipelineString)
443 | {
444 | try
445 | {
446 | if (m_pipelineBuilt == true)
447 | {
448 | cout << "Cancelling -parsestring. Another pipeline has already been built." << endl;
449 | return false;
450 | }
451 |
452 | cout << "Applying this Pipeline to the CInstantCameraAppsc: " << pipelineString << "..." << endl;
453 |
454 | string strPipeline = "";
455 | if (pipelineString.find("gst-launch") != std::string::npos)
456 | {
457 | std::size_t start = pipelineString.find("!");
458 | strPipeline = pipelineString.substr(start);
459 | }
460 | else
461 | strPipeline = pipelineString;
462 |
463 | GstElement *userPipeline;
464 | userPipeline = gst_parse_bin_from_description(strPipeline.c_str(), true, NULL);
465 |
466 | // add and link the pipeline elements
467 | gst_bin_add_many(GST_BIN(m_pipeline), m_source, userPipeline, NULL);
468 | gst_element_link_many(m_source, userPipeline, NULL);
469 |
470 | cout << "Pipeline Made." << endl;
471 |
472 | m_pipelineBuilt = true;
473 |
474 | return true;
475 | }
476 | catch (std::exception &e)
477 | {
478 | cerr << "An exception occurred in build_pipeline_parsestring(): " << endl << e.what() << endl;
479 | return false;
480 | }
481 | }
482 |
483 |
484 | // ****************************************************************************
485 | // debugging functions
486 |
487 | static gboolean print_field (GQuark field, const GValue * value, gpointer pfx) {
488 | gchar *str = gst_value_serialize (value);
489 |
490 | g_print ("%s %15s: %s\n", (gchar *) pfx, g_quark_to_string (field), str);
491 | g_free (str);
492 | return TRUE;
493 | }
494 |
495 | static void print_caps (const GstCaps * caps, const gchar * pfx) {
496 | guint i;
497 |
498 | g_return_if_fail (caps != NULL);
499 |
500 | if (gst_caps_is_any (caps)) {
501 | g_print ("%sANY\n", pfx);
502 | return;
503 | }
504 | if (gst_caps_is_empty (caps)) {
505 | g_print ("%sEMPTY\n", pfx);
506 | return;
507 | }
508 |
509 | for (i = 0; i < gst_caps_get_size (caps); i++) {
510 | GstStructure *structure = gst_caps_get_structure (caps, i);
511 |
512 | g_print ("%s%s\n", pfx, gst_structure_get_name (structure));
513 | gst_structure_foreach (structure, print_field, (gpointer) pfx);
514 | }
515 | }
516 |
517 | /* Prints information about a Pad Template, including its Capabilities */
518 | static void print_pad_templates_information (GstElementFactory * factory) {
519 | const GList *pads;
520 | GstStaticPadTemplate *padtemplate;
521 |
522 | g_print ("Pad Templates for %s:\n", gst_element_factory_get_longname (factory));
523 | if (!gst_element_factory_get_num_pad_templates (factory)) {
524 | g_print (" none\n");
525 | return;
526 | }
527 |
528 | pads = gst_element_factory_get_static_pad_templates (factory);
529 | while (pads) {
530 | padtemplate = (GstStaticPadTemplate*)pads->data;
531 | pads = g_list_next (pads);
532 |
533 | if (padtemplate->direction == GST_PAD_SRC)
534 | g_print (" SRC template: '%s'\n", padtemplate->name_template);
535 | else if (padtemplate->direction == GST_PAD_SINK)
536 | g_print (" SINK template: '%s'\n", padtemplate->name_template);
537 | else
538 | g_print (" UNKNOWN!!! template: '%s'\n", padtemplate->name_template);
539 |
540 | if (padtemplate->presence == GST_PAD_ALWAYS)
541 | g_print (" Availability: Always\n");
542 | else if (padtemplate->presence == GST_PAD_SOMETIMES)
543 | g_print (" Availability: Sometimes\n");
544 | else if (padtemplate->presence == GST_PAD_REQUEST)
545 | g_print (" Availability: On request\n");
546 | else
547 | g_print (" Availability: UNKNOWN!!!\n");
548 |
549 | if (padtemplate->static_caps.string) {
550 | GstCaps *caps;
551 | g_print (" Capabilities:\n");
552 | caps = gst_static_caps_get (&padtemplate->static_caps);
553 | print_caps (caps, " ");
554 | gst_caps_unref (caps);
555 |
556 | }
557 |
558 | g_print ("\n");
559 | }
560 | }
561 |
562 | /* Shows the CURRENT capabilities of the requested pad in the given element */
563 | static void print_pad_capabilities (GstElement *element, gchar *pad_name) {
564 | GstPad *pad = NULL;
565 | GstCaps *caps = NULL;
566 |
567 | /* Retrieve pad */
568 | pad = gst_element_get_static_pad (element, pad_name);
569 | if (!pad) {
570 | g_printerr ("Could not retrieve pad '%s'\n", pad_name);
571 | return;
572 | }
573 |
574 | /* Retrieve negotiated caps (or acceptable caps if negotiation is not finished yet) */
575 | caps = gst_pad_get_current_caps (pad);
576 | if (!caps)
577 | caps = gst_pad_query_caps (pad, NULL);
578 |
579 | /* Print and free */
580 | g_print ("Caps for the %s pad:\n", pad_name);
581 | print_caps (caps, " ");
582 | gst_caps_unref (caps);
583 | gst_object_unref (pad);
584 | }
585 | // ****************************************************************************
586 |
--------------------------------------------------------------------------------
/Samples/demopylongstreamer/demopylongstreamer.cpp:
--------------------------------------------------------------------------------
1 | /* demopylongstreamer.cpp: Sample application using CInstantCameraAppSrc class.
2 | This will stream image data from a Basler camera to a GStreamer pipeline.
3 | CPipelineHelper is included to help create sample pipelines
4 | CInstantCameraAppSrc and CPipelineHelper are intended to be used as modules, so that functionality can be added over time.
5 |
6 | Copyright 2017 Matthew Breit
7 |
8 | Licensed under the Apache License, Version 2.0 (the "License");
9 | you may not use this file except in compliance with the License.
10 | You may obtain a copy of the License at
11 |
12 | http://www.apache.org/licenses/LICENSE-2.0
13 |
14 | Unless required by applicable law or agreed to in writing, software
15 | distributed under the License is distributed on an "AS IS" BASIS,
16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | See the License for the specific language governing permissions and
18 | limitations under the License.
19 |
20 | THIS SOFTWARE REQUIRES ADDITIONAL SOFTWARE (IE: LIBRARIES) IN ORDER TO COMPILE
21 | INTO BINARY FORM AND TO FUNCTION IN BINARY FORM. ANY SUCH ADDITIONAL SOFTWARE
22 | IS OUTSIDE THE SCOPE OF THIS LICENSE.
23 |
24 |
25 | DemoPylonGStreamer:
26 | Demo of InstantCameraAppSrc class (and PipelineHelper).
27 |
28 | Concept Overview:
29 | <--------------- InstantCameraAppSrc --------------> <------------ PipelineHelper ----------->
30 | +--------------------------------------------------+ +---------+ +---------+ +---------+
31 | | source | | element | | element | | sink |
32 | | (camera + driver + GstAppSrc + rescale + rotate) | | | | | | |
33 | | src--sink src--sink src--sink |
34 | +--------------------------------------------------+ +---------+ +---------+ +---------+
35 |
36 | Usage:
37 | demopylongstreamer -options -pipeline
38 |
39 | Options:
40 | -camera (Use a specific camera. If not specified, will use first camera found.)
41 | -aoi (Camera's Area Of Interest. If not specified, will use camera's maximum.)
42 | -rescale (Will rescale the image for the pipeline if desired.)
43 | -rotate (Will rotate 90, 180, 270 degrees clockwise)
44 | -framerate (If not specified, will use camera's maximum under current settings.)
45 | -ondemand (Will software trigger the camera when needed instead of using continuous free run. May lower CPU load.)
46 | -usetrigger (Will configure the camera to expect a hardware trigger on IO Line 1. eg: TTL signal.)
47 |
48 | Pipeline Examples (pick one):
49 | -h264stream (Encodes images as h264 and transmits stream to another PC running a GStreamer receiving pipeline.)
50 | -h264file (Encodes images as h264 and records stream to local file.)
51 | -window (displays the raw image stream in a window on the local machine.)
52 | -framebuffer (directs raw image stream to Linux framebuffer. eg: /dev/fb0)
53 | -parse (try your existing gst-launch-1.0 pipeline string. We will replace the original pipeline source with the Basler camera.)
54 |
55 | Examples:
56 | demopylongstreamer -window
57 | demopylongstreamer -camera 12345678 -aoi 640 480 -framerate 15 -rescale 320 240 -h264file mymovie.h264
58 | demopylongstreamer -rescale 320 240 -parse "gst-launch-1.0 videotestsrc ! videoflip method=vertical-flip ! videoconvert ! autovideosink"
59 |
60 | Quick-Start Example:
61 | demopylongstreamer -window
62 |
63 | NVIDIA TX1/TX2 Note:
64 | When using autovideosink for display, the system-preferred built-in videosink plugin does advertise the formats it supports. So the image must be converted manually.
65 | For an example of how to do this, see CPipelineHelper::build_pipeline_display().
66 | If you are using demopylongstreamer with the -parse argument in order to use your own pipeline, add a caps filter after the normal videoconvert and before autovideosink:
67 | ./demopylongstreamer -parse "gst-launch-1.0 videotestsrc ! videoflip method=vertical-flip ! videoconvert ! video/x-raw,format=I420 ! autovideosink"
68 |
69 | Note:
70 | Some GStreamer elements (plugins) used in the pipeline examples may not be available on all systems. Consult GStreamer for more information:
71 | https://gstreamer.freedesktop.org/
72 | */
73 |
74 |
75 | #include "../../InstantCameraAppSrc/CInstantCameraAppSrc.h"
76 | #include "CPipelineHelper.h"
77 | #include
78 |
79 | using namespace std;
80 |
81 | int exitCode = 0;
82 |
83 | // ******* variables, call-backs, etc. for use with gstreamer ********
84 | // The main event loop manages all the available sources of events for GLib and GTK+ applications
85 | GMainLoop *loop;
86 | // The GstBus is an object responsible for delivering GstMessage packets in a first-in first-out way from the streaming threads
87 | GstBus *bus;
88 | guint bus_watch_id;
89 |
90 | // we link elements together in a pipeline, and send messages to/from the pipeline.
91 | GstElement *pipeline;
92 |
93 | // handler for bus call messages
94 | gboolean bus_call(GstBus *bus, GstMessage *msg, gpointer data)
95 | {
96 | try
97 | {
98 | GMainLoop *loop = (GMainLoop *)data;
99 |
100 | switch (GST_MESSAGE_TYPE(msg)) {
101 |
102 | case GST_MESSAGE_EOS:
103 | g_print("End of stream\n");
104 | g_main_loop_quit(loop);
105 | break;
106 |
107 | case GST_MESSAGE_ERROR: {
108 | gchar *debug;
109 | GError *error;
110 |
111 | gst_message_parse_error(msg, &error, &debug);
112 | g_printerr ("ERROR from element %s: %s\n", GST_OBJECT_NAME (msg->src), error->message);
113 | g_printerr ("Debugging info: %s\n", (debug) ? debug : "none");
114 |
115 | g_error_free(error);
116 | g_free(debug);
117 |
118 | g_main_loop_quit(loop);
119 | break;
120 | }
121 |
122 | default:
123 | break;
124 | }
125 |
126 | return TRUE;
127 | }
128 | catch (std::exception &e)
129 | {
130 | cerr << "An exception occurred in bus_call(): " << endl << e.what() << endl;
131 | return FALSE;
132 | }
133 | }
134 |
135 | static void sigint_restore()
136 | {
137 | try
138 | {
139 | #ifndef WIN32
140 | struct sigaction action;
141 | memset(&action, 0, sizeof(action));
142 | action.sa_handler = SIG_DFL;
143 | sigaction(SIGINT, &action, NULL);
144 | #endif
145 | }
146 | catch (std::exception &e)
147 | {
148 | cerr << "An exception occurred in sigint_restore(): " << endl << e.what() << endl;
149 | }
150 | }
151 |
152 | // Signal handler for ctrl+c
153 | void IntHandler(int dummy)
154 | {
155 | try
156 | {
157 | // send End Of Stream event to all pipeline elements
158 | cout << endl;
159 | cout << "Sending EOS event to pipeline..." << endl;
160 | gst_element_send_event(pipeline, gst_event_new_eos());
161 | sigint_restore();
162 | return;
163 | }
164 | catch (std::exception &e)
165 | {
166 | cerr << "An exception occurred in IntHandler(): " << endl << e.what() << endl;
167 | }
168 | }
169 |
170 | // ******* END variables, call-backs, etc. for use with gstreamer ********
171 |
172 | // *********** Command line argument variables and parser **************
173 | // quick-start settings for AOI and framerate. Use maximum possible camera resultion and maximum possible framerate @ resolution.
174 | int width = -1;
175 | int height = -1;
176 | int frameRate = -1;
177 |
178 | int numImagesToRecord = -1; // capture indefinitley unless otherwise specified.
179 | int scaledWidth = -1; // do not scale by default
180 | int scaledHeight = -1;
181 | int rotation = -1; // do not rotate or flip image by default
182 | bool h264stream = false;
183 | bool h264multicast = false;
184 | bool h264file = false;
185 | bool display = false;
186 | bool framebuffer = false;
187 | bool parsestring = false;
188 | bool onDemand = false;
189 | bool useTrigger = false;
190 | string serialNumber = "";
191 | string ipaddress = "";
192 | string filename = "";
193 | string fbdev = "";
194 | string pipelineString = "";
195 |
196 | int ParseCommandLine(gint argc, gchar *argv[])
197 | {
198 | try
199 | {
200 | if (argc < 2)
201 | {
202 | cout << endl;
203 | cout << "DemoPylonGStreamer: " << endl;
204 | cout << " Demo of InstantCameraAppSrc class (and PipelineHelper)." << endl;
205 | cout << endl;
206 | cout << "Concept Overview:" << endl;
207 | cout << " <--------------- InstantCameraAppSrc --------------> <------------ PipelineHelper ----------->" << endl;
208 | cout << " +--------------------------------------------------+ +---------+ +---------+ +---------+" << endl;
209 | cout << " | source | | element | | element | | sink |" << endl;
210 | cout << " | (camera + driver + GstAppSrc + rescale + rotate) | | | | | | |" << endl;
211 | cout << " | src--sink src--sink src--sink |" << endl;
212 | cout << " +--------------------------------------------------+ +---------+ +---------+ +---------+" << endl;
213 | cout << endl;
214 | cout << "Usage:" << endl;
215 | cout << " demopylongstreamer -options -pipeline" << endl;
216 | cout << endl;
217 | cout << "Options: " << endl;
218 | cout << " -camera (Use a specific camera. If not specified, will use first camera found.)" << endl;
219 | cout << " -aoi (Camera's Area Of Interest. If not specified, will use camera's maximum.)" << endl;
220 | cout << " -rescale (Will rescale the image for the pipeline if desired.)" << endl;
221 | cout << " -rotate (Will rotate 90, 180, 270 degrees clockwise)" << endl;
222 | cout << " -framerate (If not specified, will use camera's maximum under current settings.)" << endl;
223 | cout << " -ondemand (Will software trigger the camera when needed instead of using continuous free run. May lower CPU load.)" << endl;
224 | cout << " -usetrigger (Will configure the camera to expect a hardware trigger on IO Line 1. eg: TTL signal.)" << endl;
225 | cout << endl;
226 | cout << "Pipeline Examples (pick one):" << endl;
227 | cout << " -h264stream (Encodes images as h264 and transmits stream to another PC running a GStreamer receiving pipeline.)" << endl;
228 | cout << " -h264multicast (Encodes images as h264 and multicasts stream to the network.)" << endl;
229 | cout << " -h264file (Encodes images as h264 and records stream to local file.)" << endl;
230 | cout << " -window (displays the raw image stream in a window on the local machine.)" << endl;
231 | cout << " -framebuffer (directs raw image stream to Linux framebuffer. eg: /dev/fb0)" << endl;
232 | cout << " -parse (try your existing gst-launch-1.0 pipeline string. We will replace the original pipeline source with the Basler camera if needed.)" << endl;
233 | cout << endl;
234 | cout << "Examples: " << endl;
235 | cout << " demopylongstreamer -framebuffer /dev/fb0" << endl;
236 | cout << " demopylongstreamer -rescale 640 480 -h264stream 172.17.1.199" << endl;
237 | cout << " demopylongstreamer -camera 12345678 -aoi 640 480 -framerate 15 -rescale 320 240 -h264file mymovie.h264" << endl;
238 | cout << " demopylongstreamer -rescale 320 240 -parse \"gst-launch-1.0 videotestsrc ! videoflip method=vertical-flip ! videoconvert ! autovideosink\"" << endl;
239 | cout << " demopylongstreamer -rescale 320 240 -parse \"videoflip method=vertical-flip ! videoconvert ! autovideosink\"" << endl;
240 | cout << endl;
241 | cout << "Quick-Start Example to display stream:" << endl;
242 | cout << " demopylongstreamer -window" << endl;
243 | cout << endl;
244 | cout << "NVIDIA TX1/TX2 Note:" << endl;
245 | cout << "When using autovideosink for display, the system-preferred built-in videosink plugin does advertise the formats it supports. So the image must be converted manually." << endl;
246 | cout << "For an example of how to do this, see CPipelineHelper::build_pipeline_display()." << endl;
247 | cout << "If you are using demopylongstreamer with the -parse argument in order to use your own pipeline, add a caps filter after the normal videoconvert and before autovideosink:" << endl;
248 | cout << "./demopylongstreamer -parse \"gst-launch-1.0 videotestsrc ! videoflip method=vertical-flip ! videoconvert ! video/x-raw,format=I420 ! autovideosink\"" << endl;
249 | cout << endl;
250 | cout << "Note:" << endl;
251 | cout << " Some GStreamer elements (plugins) used in the pipeline examples may not be available on all systems. Consult GStreamer for more information:" << endl;
252 | cout << " https://gstreamer.freedesktop.org/" << endl;
253 | cout << endl;
254 |
255 | return -1;
256 | }
257 |
258 | for (int i = 1; i < argc; i++)
259 | {
260 | if (string(argv[i]) == "-camera")
261 | {
262 | if (argv[i + 1] != NULL)
263 | serialNumber = string(argv[i + 1]);
264 | else
265 | {
266 | cout << "Serial number not specified. eg: -camera 21045367" << endl;
267 | return -1;
268 | }
269 | }
270 | else if (string(argv[i]) == "-aoi")
271 | {
272 | if (argv[i + 1] != NULL)
273 | width = atoi(argv[i + 1]);
274 | else
275 | {
276 | cout << "AOI width not specified. eg: -aoi 320 240" << endl;
277 | return -1;
278 | }
279 | if (argv[i + 2] != NULL)
280 | height = atoi(argv[i + 2]);
281 | else
282 | {
283 | cout << "AOI height not specified. eg: -aoi 320 240" << endl;
284 | return -1;
285 | }
286 | }
287 | else if (string(argv[i]) == "-rescale")
288 | {
289 | if (argv[i + 1] != NULL)
290 | scaledWidth = atoi(argv[i + 1]);
291 | else
292 | {
293 | cout << "Scaling width not specified. eg: -scaled 320 240" << endl;
294 | return -1;
295 | }
296 | if (argv[i + 2] != NULL)
297 | scaledHeight = atoi(argv[i + 2]);
298 | else
299 | {
300 | cout << "Scaling height not specified. eg: -scaled 320 240" << endl;
301 | return -1;
302 | }
303 | }
304 | else if (string(argv[i]) == "-rotate")
305 | {
306 | if (argv[i + 1] != NULL)
307 | rotation = atoi(argv[i + 1]);
308 | else
309 | {
310 | cout << "Rotation not specified. eg: -rotate 90" << endl;
311 | return -1;
312 | }
313 | }
314 | else if (string(argv[i]) == "-framerate")
315 | {
316 | if (argv[i + 1] != NULL)
317 | frameRate = atoi(argv[i + 1]);
318 | else
319 | {
320 | cout << "Framerate not specified. eg: -framerate 100" << endl;
321 | return -1;
322 | }
323 | }
324 | else if (string(argv[i]) == "-ondemand")
325 | {
326 | onDemand = true;
327 | }
328 | else if (string(argv[i]) == "-usetrigger")
329 | {
330 | useTrigger = true;
331 | }
332 | else if (string(argv[i]) == "-h264stream")
333 | {
334 | h264stream = true;
335 | if (argv[i + 1] != NULL)
336 | ipaddress = string(argv[i + 1]);
337 | else
338 | {
339 | cout << "IP Address not specified. eg: -h264stream 192.168.2.102" << endl;
340 | return -1;
341 | }
342 | }
343 | else if (string(argv[i]) == "-h264multicast")
344 | {
345 | h264multicast = true;
346 | if (argv[i + 1] != NULL)
347 | ipaddress = string(argv[i + 1]);
348 | else
349 | {
350 | cout << "IP Address not specified. eg: -h264multicast 224.1.1.1" << endl;
351 | return -1;
352 | }
353 | }
354 | else if (string(argv[i]) == "-h264file")
355 | {
356 | h264file = true;
357 | if (argv[i + 1] != NULL)
358 | filename = string(argv[i + 1]);
359 | else
360 | {
361 | cout << "Filename not specified. eg: -h264file filename 100" << endl;
362 | return -1;
363 | }
364 | if (argv[i + 2] != NULL)
365 | numImagesToRecord = atoi(argv[i + 2]);
366 | else
367 | {
368 | cout << "Number of images not specified. eg: -h264file filename 100" << endl;
369 | return -1;
370 | }
371 | }
372 | else if (string(argv[i]) == "-window")
373 | {
374 | display = true;
375 | }
376 | else if (string(argv[i]) == "-framebuffer")
377 | {
378 | framebuffer = true;
379 | if (argv[i + 1] != NULL)
380 | fbdev = string(argv[i + 1]);
381 | else
382 | {
383 | cout << "Framebuffer not specified. eg: -framebuffer /dev/fb0" << endl;
384 | return -1;
385 | }
386 | }
387 | else if (string(argv[i]) == "-parse")
388 | {
389 | parsestring = true;
390 | if (argv[i + 1] != NULL)
391 | pipelineString = string(argv[i + 1]);
392 | else
393 | {
394 | cout << "pipeline string not specified. Use one of these format with quotes: \"gst-launch-1.0 videotestsrc ! videoflip method=vertical-flip ! videoconvert ! autovideosink\" or \"videoflip method=vertical-flip ! videoconvert ! autovideosink\"" << endl;
395 | return -1;
396 | }
397 | }
398 | // deprecated
399 | else if (string(argv[i]) == "-display")
400 | {
401 | display = true;
402 | }
403 | // deprecated
404 | else if (string(argv[i]) == "-width")
405 | {
406 | if (argv[i + 1] != NULL)
407 | width = atoi(argv[i + 1]);
408 | else
409 | {
410 | cout << "Width not specified. eg: -width 640" << endl;
411 | return -1;
412 | }
413 | }
414 | // deprecated
415 | else if (string(argv[i]) == "-height")
416 | {
417 | if (argv[i + 1] != NULL)
418 | height = atoi(argv[i + 1]);
419 | else
420 | {
421 | cout << "Height not specified. eg: -height 480" << endl;
422 | return -1;
423 | }
424 | }
425 | }
426 |
427 | bool pipelinesAvailable[] = { display, framebuffer, h264file, h264stream, h264multicast, parsestring };
428 | int pipelinesRequested = 0;
429 |
430 | for (int i = 0; i < sizeof(pipelinesAvailable); i++)
431 | pipelinesRequested += (int)pipelinesAvailable[i];
432 |
433 | if (pipelinesRequested == 0)
434 | {
435 | cout << "No Pipeline Specified. Please specifiy one (and only one)." << endl;
436 | return -1;
437 | }
438 |
439 | if (pipelinesRequested > 1)
440 | {
441 | cout << "Too Many Pipelines Specified. Please use only one." << endl;
442 | return -1;
443 | }
444 |
445 | return 0;
446 | }
447 | catch (GenICam::GenericException &e)
448 | {
449 | cerr << "An exception occured in ParseCommandLine(): " << endl << e.GetDescription() << endl;
450 | return -1;
451 | }
452 | catch (std::exception &e)
453 | {
454 | cerr << "An exception occurred in ParseCommandLine(): " << endl << e.what() << endl;
455 | return -1;
456 | }
457 | }
458 |
459 | // *********** END Command line argument variables and parser **************
460 |
461 | gint main(gint argc, gchar *argv[])
462 | {
463 |
464 | try
465 | {
466 |
467 | if (ParseCommandLine(argc, argv) == -1)
468 | {
469 | exitCode = -1;
470 | return exitCode;
471 | }
472 |
473 | // signal handler for ctrl+C
474 | signal(SIGINT, IntHandler);
475 |
476 | cout << "Press CTRL+C at any time to quit." << endl;
477 |
478 | // initialize GStreamer
479 | gst_init(NULL, NULL);
480 |
481 | // create the mainloop
482 | loop = g_main_loop_new(NULL, FALSE);
483 |
484 | // The InstantCameraForAppSrc will manage the camera and driver
485 | // and provide a source element to the GStreamer pipeline.
486 | CInstantCameraAppSrc camera(serialNumber);
487 |
488 | // reset the camera to defaults if you like
489 | cout << "Resetting camera to default settings..." << endl;
490 | camera.ResetCamera();
491 |
492 | // Initialize the camera and driver
493 | cout << "Initializing camera and driver..." << endl;
494 | camera.InitCamera(width, height, frameRate, onDemand, useTrigger, scaledWidth, scaledHeight, rotation, numImagesToRecord);
495 |
496 | cout << "Using Camera : " << camera.GetDeviceInfo().GetFriendlyName() << endl;
497 | cout << "Camera Area Of Interest : " << camera.GetWidth() << "x" << camera.GetHeight() << endl;
498 | cout << "Camera Speed : " << camera.GetFrameRate() << " fps" << endl;
499 | if (scaledWidth != -1 && scaledHeight != -1)
500 | cout << "Images will be scaled to : " << scaledWidth << "x" << scaledHeight << endl;
501 | if (rotation != -1)
502 | cout << "Images will be rotated : " << rotation << " degrees clockwise" << endl;
503 |
504 | // create a new pipeline to add elements too
505 | pipeline = gst_pipeline_new("pipeline");
506 |
507 | // prepare a handler (watcher) for messages from the pipeline
508 | bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));
509 | bus_watch_id = gst_bus_add_watch(bus, bus_call, loop);
510 | gst_object_unref(bus);
511 |
512 | // A pipeline needs a source element. The InstantCameraForAppSrc will create, configure, and provide an AppSrc which fits the camera.
513 | GstElement *source = camera.GetSource();
514 |
515 | // Build the rest of the pipeline based on the sample chosen.
516 | // The PipelineHelper will manage the configuration of GStreamer pipelines.
517 | // The pipeline helper can be expanded to create several kinds of pipelines
518 | // as these can depend heavily on the application and host capabilities.
519 | // Rescaling the image is optional. In this sample we do rescaling and rotation in the InstantCameraAppSrc.
520 | CPipelineHelper myPipelineHelper(pipeline, source);
521 |
522 | bool pipelineBuilt = false;
523 |
524 | if (display == true)
525 | pipelineBuilt = myPipelineHelper.build_pipeline_display();
526 | else if (h264stream == true)
527 | pipelineBuilt = myPipelineHelper.build_pipeline_h264stream(ipaddress.c_str());
528 | else if (h264multicast == true)
529 | pipelineBuilt = myPipelineHelper.build_pipeline_h264multicast(ipaddress.c_str());
530 | else if (h264file == true)
531 | pipelineBuilt = myPipelineHelper.build_pipeline_h264file(filename.c_str());
532 | else if (framebuffer == true)
533 | pipelineBuilt = myPipelineHelper.build_pipeline_framebuffer(fbdev.c_str());
534 | else if (parsestring == true)
535 | pipelineBuilt = myPipelineHelper.build_pipeline_parsestring(pipelineString.c_str());
536 |
537 | if (pipelineBuilt == false)
538 | {
539 | exitCode = -1;
540 | throw std::runtime_error("Pipeline building failed!");
541 | }
542 |
543 | // Start the camera and grab engine.
544 | if (camera.StartCamera() == false)
545 | {
546 | exitCode = -1;
547 | throw std::runtime_error("Could not start camera!");
548 | }
549 |
550 | // Start the pipeline.
551 | cout << "Starting pipeline..." << endl;
552 | gst_element_set_state(pipeline, GST_STATE_PLAYING);
553 |
554 | // run the main loop. When Ctrl+C is pressed, an EOS event will be sent
555 | // which will shutdown the pipeline in intHandler(), which will in turn quit the main loop.
556 | g_main_loop_run(loop);
557 |
558 | // clean up
559 | cout << "Stopping pipeline..." << endl;
560 | gst_element_set_state(pipeline, GST_STATE_NULL);
561 |
562 | camera.StopCamera();
563 | camera.CloseCamera();
564 |
565 | gst_object_unref(GST_OBJECT(pipeline));
566 | g_main_loop_unref(loop);
567 |
568 | exitCode = 0;
569 |
570 | }
571 | catch (GenICam::GenericException &e)
572 | {
573 | cerr << "An exception occured in main(): " << endl << e.GetDescription() << endl;
574 | exitCode = -1;
575 |
576 | }
577 | catch (std::exception &e)
578 | {
579 | cerr << "An exception occurred in main(): " << endl << e.what() << endl;
580 | exitCode = -1;
581 | }
582 |
583 | // Comment the following two lines to disable waiting on exit.
584 | cerr << endl << "Press Enter to exit." << endl;
585 | while (cin.get() != '\n');
586 |
587 | return exitCode;
588 | }
589 |
--------------------------------------------------------------------------------
/Samples/demopylongstreamer_jetson_performance/demopylongstreamer.cpp:
--------------------------------------------------------------------------------
1 | /* demopylongstreamer.cpp: Sample application using CInstantCameraAppSrc class.
2 | This will stream image data from a Basler camera to a GStreamer pipeline.
3 | CPipelineHelper is included to help create sample pipelines
4 | CInstantCameraAppSrc and CPipelineHelper are intended to be used as modules, so that functionality can be added over time.
5 |
6 | Copyright 2017 Matthew Breit
7 |
8 | Licensed under the Apache License, Version 2.0 (the "License");
9 | you may not use this file except in compliance with the License.
10 | You may obtain a copy of the License at
11 |
12 | http://www.apache.org/licenses/LICENSE-2.0
13 |
14 | Unless required by applicable law or agreed to in writing, software
15 | distributed under the License is distributed on an "AS IS" BASIS,
16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | See the License for the specific language governing permissions and
18 | limitations under the License.
19 |
20 | THIS SOFTWARE REQUIRES ADDITIONAL SOFTWARE (IE: LIBRARIES) IN ORDER TO COMPILE
21 | INTO BINARY FORM AND TO FUNCTION IN BINARY FORM. ANY SUCH ADDITIONAL SOFTWARE
22 | IS OUTSIDE THE SCOPE OF THIS LICENSE.
23 |
24 |
25 | DemoPylonGStreamer:
26 | Demo of InstantCameraAppSrc class (and PipelineHelper).
27 |
28 | Concept Overview:
29 | <--------------- InstantCameraAppSrc --------------> <------------ PipelineHelper ----------->
30 | +--------------------------------------------------+ +---------+ +---------+ +---------+
31 | | source | | element | | element | | sink |
32 | | (camera + driver + GstAppSrc + rescale + rotate) | | | | | | |
33 | | src--sink src--sink src--sink |
34 | +--------------------------------------------------+ +---------+ +---------+ +---------+
35 |
36 | Usage:
37 | demopylongstreamer -options -pipeline
38 |
39 | Options:
40 | -camera (Use a specific camera. If not specified, will use first camera found.)
41 | -aoi (Camera's Area Of Interest. If not specified, will use camera's maximum.)
42 | -rescale (Will rescale the image for the pipeline if desired.)
43 | -rotate (Will rotate 90, 180, 270 degrees clockwise)
44 | -framerate (If not specified, will use camera's maximum under current settings.)
45 | -ondemand (Will software trigger the camera when needed instead of using continuous free run. May lower CPU load.)
46 | -usetrigger (Will configure the camera to expect a hardware trigger on IO Line 1. eg: TTL signal.)
47 |
48 | Pipeline Examples (pick one):
49 | -h264stream (Encodes images as h264 and transmits stream to another PC running a GStreamer receiving pipeline.)
50 | -h264file (Encodes images as h264 and records stream to local file.)
51 | -window (displays the raw image stream in a window on the local machine.)
52 | -framebuffer (directs raw image stream to Linux framebuffer. eg: /dev/fb0)
53 | -parse (try your existing gst-launch-1.0 pipeline string. We will replace the original pipeline source with the Basler camera.)
54 |
55 | Examples:
56 | demopylongstreamer -window
57 | demopylongstreamer -camera 12345678 -aoi 640 480 -framerate 15 -rescale 320 240 -h264file mymovie.h264
58 | demopylongstreamer -rescale 320 240 -parse "gst-launch-1.0 videotestsrc ! videoflip method=vertical-flip ! videoconvert ! autovideosink"
59 |
60 | Quick-Start Example:
61 | demopylongstreamer -window
62 |
63 | NVIDIA TX1/TX2 Note:
64 | When using autovideosink for display, the system-preferred built-in videosink plugin does advertise the formats it supports. So the image must be converted manually.
65 | For an example of how to do this, see CPipelineHelper::build_pipeline_display().
66 | If you are using demopylongstreamer with the -parse argument in order to use your own pipeline, add a caps filter after the normal videoconvert and before autovideosink:
67 | ./demopylongstreamer -parse "gst-launch-1.0 videotestsrc ! videoflip method=vertical-flip ! videoconvert ! video/x-raw,format=I420 ! autovideosink"
68 |
69 | Note:
70 | Some GStreamer elements (plugins) used in the pipeline examples may not be available on all systems. Consult GStreamer for more information:
71 | https://gstreamer.freedesktop.org/
72 | */
73 |
74 |
75 | #include "CInstantCameraAppSrc.h"
76 | #include "CPipelineHelper.h"
77 | #include
78 |
79 | using namespace std;
80 |
81 | int exitCode = 0;
82 |
83 | // ******* variables, call-backs, etc. for use with gstreamer ********
84 | // The main event loop manages all the available sources of events for GLib and GTK+ applications
85 | GMainLoop *loop;
86 | // The GstBus is an object responsible for delivering GstMessage packets in a first-in first-out way from the streaming threads
87 | GstBus *bus;
88 | guint bus_watch_id;
89 |
90 | // we link elements together in a pipeline, and send messages to/from the pipeline.
91 | GstElement *pipeline;
92 |
93 | // handler for bus call messages
94 | gboolean bus_call(GstBus *bus, GstMessage *msg, gpointer data)
95 | {
96 | try
97 | {
98 | GMainLoop *loop = (GMainLoop *)data;
99 |
100 | switch (GST_MESSAGE_TYPE(msg)) {
101 |
102 | case GST_MESSAGE_EOS:
103 | g_print("End of stream\n");
104 | g_main_loop_quit(loop);
105 | break;
106 |
107 | case GST_MESSAGE_ERROR: {
108 | gchar *debug;
109 | GError *error;
110 |
111 | gst_message_parse_error(msg, &error, &debug);
112 | g_printerr ("ERROR from element %s: %s\n", GST_OBJECT_NAME (msg->src), error->message);
113 | g_printerr ("Debugging info: %s\n", (debug) ? debug : "none");
114 |
115 | g_error_free(error);
116 | g_free(debug);
117 |
118 | g_main_loop_quit(loop);
119 | break;
120 | }
121 |
122 | default:
123 | break;
124 | }
125 |
126 | return TRUE;
127 | }
128 | catch (std::exception &e)
129 | {
130 | cerr << "An exception occurred in bus_call(): " << endl << e.what() << endl;
131 | return FALSE;
132 | }
133 | }
134 |
135 | static void sigint_restore()
136 | {
137 | try
138 | {
139 | #ifndef WIN32
140 | struct sigaction action;
141 | memset(&action, 0, sizeof(action));
142 | action.sa_handler = SIG_DFL;
143 | sigaction(SIGINT, &action, NULL);
144 | #endif
145 | }
146 | catch (std::exception &e)
147 | {
148 | cerr << "An exception occurred in sigint_restore(): " << endl << e.what() << endl;
149 | }
150 | }
151 |
152 | // Signal handler for ctrl+c
153 | void IntHandler(int dummy)
154 | {
155 | try
156 | {
157 | // send End Of Stream event to all pipeline elements
158 | cout << endl;
159 | cout << "Sending EOS event to pipeline..." << endl;
160 | gst_element_send_event(pipeline, gst_event_new_eos());
161 | sigint_restore();
162 | return;
163 | }
164 | catch (std::exception &e)
165 | {
166 | cerr << "An exception occurred in IntHandler(): " << endl << e.what() << endl;
167 | }
168 | }
169 |
170 | // ******* END variables, call-backs, etc. for use with gstreamer ********
171 |
172 | // *********** Command line argument variables and parser **************
173 | // quick-start settings for AOI and framerate. Use maximum possible camera resultion and maximum possible framerate @ resolution.
174 | int width = -1;
175 | int height = -1;
176 | int frameRate = -1;
177 |
178 | int numImagesToRecord = -1; // capture indefinitley unless otherwise specified.
179 | int scaledWidth = -1; // do not scale by default
180 | int scaledHeight = -1;
181 | int rotation = -1; // do not rotate or flip image by default
182 | bool h264stream = false;
183 | bool h264multicast = false;
184 | bool h264file = false;
185 | bool display = false;
186 | bool framebuffer = false;
187 | bool parsestring = false;
188 | bool onDemand = false;
189 | bool useTrigger = false;
190 | string serialNumber = "";
191 | string ipaddress = "";
192 | string filename = "";
193 | string fbdev = "";
194 | string pipelineString = "";
195 |
196 | int ParseCommandLine(gint argc, gchar *argv[])
197 | {
198 | try
199 | {
200 | if (argc < 2)
201 | {
202 | cout << endl;
203 | cout << "DemoPylonGStreamer: " << endl;
204 | cout << " Demo of InstantCameraAppSrc class (and PipelineHelper)." << endl;
205 | cout << endl;
206 | cout << "Concept Overview:" << endl;
207 | cout << " <--------------- InstantCameraAppSrc --------------> <------------ PipelineHelper ----------->" << endl;
208 | cout << " +--------------------------------------------------+ +---------+ +---------+ +---------+" << endl;
209 | cout << " | source | | element | | element | | sink |" << endl;
210 | cout << " | (camera + driver + GstAppSrc + rescale + rotate) | | | | | | |" << endl;
211 | cout << " | src--sink src--sink src--sink |" << endl;
212 | cout << " +--------------------------------------------------+ +---------+ +---------+ +---------+" << endl;
213 | cout << endl;
214 | cout << "Usage:" << endl;
215 | cout << " demopylongstreamer -options -pipeline" << endl;
216 | cout << endl;
217 | cout << "Options: " << endl;
218 | cout << " -camera (Use a specific camera. If not specified, will use first camera found.)" << endl;
219 | cout << " -aoi (Camera's Area Of Interest. If not specified, will use camera's maximum.)" << endl;
220 | cout << " -rescale (Will rescale the image for the pipeline if desired.)" << endl;
221 | cout << " -rotate (Will rotate 90, 180, 270 degrees clockwise)" << endl;
222 | cout << " -framerate (If not specified, will use camera's maximum under current settings.)" << endl;
223 | cout << " -ondemand (Will software trigger the camera when needed instead of using continuous free run. May lower CPU load.)" << endl;
224 | cout << " -usetrigger (Will configure the camera to expect a hardware trigger on IO Line 1. eg: TTL signal.)" << endl;
225 | cout << endl;
226 | cout << "Pipeline Examples (pick one):" << endl;
227 | cout << " -h264stream (Encodes images as h264 and transmits stream to another PC running a GStreamer receiving pipeline.)" << endl;
228 | cout << " -h264multicast (Encodes images as h264 and multicasts stream to the network.)" << endl;
229 | cout << " -h264file (Encodes images as h264 and records stream to local file.)" << endl;
230 | cout << " -window (displays the raw image stream in a window on the local machine.)" << endl;
231 | cout << " -framebuffer (directs raw image stream to Linux framebuffer. eg: /dev/fb0)" << endl;
232 | cout << " -parse (try your existing gst-launch-1.0 pipeline string. We will replace the original pipeline source with the Basler camera if needed.)" << endl;
233 | cout << endl;
234 | cout << "Examples: " << endl;
235 | cout << " demopylongstreamer -framebuffer /dev/fb0" << endl;
236 | cout << " demopylongstreamer -rescale 640 480 -h264stream 172.17.1.199" << endl;
237 | cout << " demopylongstreamer -camera 12345678 -aoi 640 480 -framerate 15 -rescale 320 240 -h264file mymovie.h264" << endl;
238 | cout << " demopylongstreamer -rescale 320 240 -parse \"gst-launch-1.0 videotestsrc ! videoflip method=vertical-flip ! videoconvert ! autovideosink\"" << endl;
239 | cout << " demopylongstreamer -rescale 320 240 -parse \"videoflip method=vertical-flip ! videoconvert ! autovideosink\"" << endl;
240 | cout << endl;
241 | cout << "Quick-Start Example to display stream:" << endl;
242 | cout << " demopylongstreamer -window" << endl;
243 | cout << endl;
244 | cout << "NVIDIA TX1/TX2 Note:" << endl;
245 | cout << "When using autovideosink for display, the system-preferred built-in videosink plugin does advertise the formats it supports. So the image must be converted manually." << endl;
246 | cout << "For an example of how to do this, see CPipelineHelper::build_pipeline_display()." << endl;
247 | cout << "If you are using demopylongstreamer with the -parse argument in order to use your own pipeline, add a caps filter after the normal videoconvert and before autovideosink:" << endl;
248 | cout << "./demopylongstreamer -parse \"gst-launch-1.0 videotestsrc ! videoflip method=vertical-flip ! videoconvert ! video/x-raw,format=I420 ! autovideosink\"" << endl;
249 | cout << endl;
250 | cout << "Note:" << endl;
251 | cout << " Some GStreamer elements (plugins) used in the pipeline examples may not be available on all systems. Consult GStreamer for more information:" << endl;
252 | cout << " https://gstreamer.freedesktop.org/" << endl;
253 | cout << endl;
254 |
255 | return -1;
256 | }
257 |
258 | for (int i = 1; i < argc; i++)
259 | {
260 | if (string(argv[i]) == "-camera")
261 | {
262 | if (argv[i + 1] != NULL)
263 | serialNumber = string(argv[i + 1]);
264 | else
265 | {
266 | cout << "Serial number not specified. eg: -camera 21045367" << endl;
267 | return -1;
268 | }
269 | }
270 | else if (string(argv[i]) == "-aoi")
271 | {
272 | if (argv[i + 1] != NULL)
273 | width = atoi(argv[i + 1]);
274 | else
275 | {
276 | cout << "AOI width not specified. eg: -aoi 320 240" << endl;
277 | return -1;
278 | }
279 | if (argv[i + 2] != NULL)
280 | height = atoi(argv[i + 2]);
281 | else
282 | {
283 | cout << "AOI height not specified. eg: -aoi 320 240" << endl;
284 | return -1;
285 | }
286 | }
287 | else if (string(argv[i]) == "-rescale")
288 | {
289 | if (argv[i + 1] != NULL)
290 | scaledWidth = atoi(argv[i + 1]);
291 | else
292 | {
293 | cout << "Scaling width not specified. eg: -scaled 320 240" << endl;
294 | return -1;
295 | }
296 | if (argv[i + 2] != NULL)
297 | scaledHeight = atoi(argv[i + 2]);
298 | else
299 | {
300 | cout << "Scaling height not specified. eg: -scaled 320 240" << endl;
301 | return -1;
302 | }
303 | }
304 | else if (string(argv[i]) == "-rotate")
305 | {
306 | if (argv[i + 1] != NULL)
307 | rotation = atoi(argv[i + 1]);
308 | else
309 | {
310 | cout << "Rotation not specified. eg: -rotate 90" << endl;
311 | return -1;
312 | }
313 | }
314 | else if (string(argv[i]) == "-framerate")
315 | {
316 | if (argv[i + 1] != NULL)
317 | frameRate = atoi(argv[i + 1]);
318 | else
319 | {
320 | cout << "Framerate not specified. eg: -framerate 100" << endl;
321 | return -1;
322 | }
323 | }
324 | else if (string(argv[i]) == "-ondemand")
325 | {
326 | onDemand = true;
327 | }
328 | else if (string(argv[i]) == "-usetrigger")
329 | {
330 | useTrigger = true;
331 | }
332 | else if (string(argv[i]) == "-h264stream")
333 | {
334 | h264stream = true;
335 | if (argv[i + 1] != NULL)
336 | ipaddress = string(argv[i + 1]);
337 | else
338 | {
339 | cout << "IP Address not specified. eg: -h264stream 192.168.2.102" << endl;
340 | return -1;
341 | }
342 | }
343 | else if (string(argv[i]) == "-h264multicast")
344 | {
345 | h264multicast = true;
346 | if (argv[i + 1] != NULL)
347 | ipaddress = string(argv[i + 1]);
348 | else
349 | {
350 | cout << "IP Address not specified. eg: -h264multicast 224.1.1.1" << endl;
351 | return -1;
352 | }
353 | }
354 | else if (string(argv[i]) == "-h264file")
355 | {
356 | h264file = true;
357 | if (argv[i + 1] != NULL)
358 | filename = string(argv[i + 1]);
359 | else
360 | {
361 | cout << "Filename not specified. eg: -h264file filename 100" << endl;
362 | return -1;
363 | }
364 | if (argv[i + 2] != NULL)
365 | numImagesToRecord = atoi(argv[i + 2]);
366 | else
367 | {
368 | cout << "Number of images not specified. eg: -h264file filename 100" << endl;
369 | return -1;
370 | }
371 | }
372 | else if (string(argv[i]) == "-window")
373 | {
374 | display = true;
375 | }
376 | else if (string(argv[i]) == "-framebuffer")
377 | {
378 | framebuffer = true;
379 | if (argv[i + 1] != NULL)
380 | fbdev = string(argv[i + 1]);
381 | else
382 | {
383 | cout << "Framebuffer not specified. eg: -framebuffer /dev/fb0" << endl;
384 | return -1;
385 | }
386 | }
387 | else if (string(argv[i]) == "-parse")
388 | {
389 | parsestring = true;
390 | if (argv[i + 1] != NULL)
391 | pipelineString = string(argv[i + 1]);
392 | else
393 | {
394 | cout << "pipeline string not specified. Use one of these format with quotes: \"gst-launch-1.0 videotestsrc ! videoflip method=vertical-flip ! videoconvert ! autovideosink\" or \"videoflip method=vertical-flip ! videoconvert ! autovideosink\"" << endl;
395 | return -1;
396 | }
397 | }
398 | // deprecated
399 | else if (string(argv[i]) == "-display")
400 | {
401 | display = true;
402 | }
403 | // deprecated
404 | else if (string(argv[i]) == "-width")
405 | {
406 | if (argv[i + 1] != NULL)
407 | width = atoi(argv[i + 1]);
408 | else
409 | {
410 | cout << "Width not specified. eg: -width 640" << endl;
411 | return -1;
412 | }
413 | }
414 | // deprecated
415 | else if (string(argv[i]) == "-height")
416 | {
417 | if (argv[i + 1] != NULL)
418 | height = atoi(argv[i + 1]);
419 | else
420 | {
421 | cout << "Height not specified. eg: -height 480" << endl;
422 | return -1;
423 | }
424 | }
425 | }
426 |
427 | bool pipelinesAvailable[] = { display, framebuffer, h264file, h264stream, h264multicast, parsestring };
428 | int pipelinesRequested = 0;
429 |
430 | for (int i = 0; i < sizeof(pipelinesAvailable); i++)
431 | pipelinesRequested += (int)pipelinesAvailable[i];
432 |
433 | if (pipelinesRequested == 0)
434 | {
435 | cout << "No Pipeline Specified. Please specifiy one (and only one)." << endl;
436 | return -1;
437 | }
438 |
439 | if (pipelinesRequested > 1)
440 | {
441 | cout << "Too Many Pipelines Specified. Please use only one." << endl;
442 | return -1;
443 | }
444 |
445 | return 0;
446 | }
447 | catch (GenICam::GenericException &e)
448 | {
449 | cerr << "An exception occured in ParseCommandLine(): " << endl << e.GetDescription() << endl;
450 | return -1;
451 | }
452 | catch (std::exception &e)
453 | {
454 | cerr << "An exception occurred in ParseCommandLine(): " << endl << e.what() << endl;
455 | return -1;
456 | }
457 | }
458 |
459 | // *********** END Command line argument variables and parser **************
460 |
461 | gint main(gint argc, gchar *argv[])
462 | {
463 |
464 | try
465 | {
466 |
467 | if (ParseCommandLine(argc, argv) == -1)
468 | {
469 | exitCode = -1;
470 | return exitCode;
471 | }
472 |
473 | // signal handler for ctrl+C
474 | signal(SIGINT, IntHandler);
475 |
476 | cout << "Press CTRL+C at any time to quit." << endl;
477 |
478 | // initialize GStreamer
479 | gst_init(NULL, NULL);
480 |
481 | // create the mainloop
482 | loop = g_main_loop_new(NULL, FALSE);
483 |
484 | // The InstantCameraForAppSrc will manage the camera and driver
485 | // and provide a source element to the GStreamer pipeline.
486 | CInstantCameraAppSrc camera(serialNumber);
487 |
488 | // reset the camera to defaults if you like
489 | cout << "Using Current Camera Settings. Skipping Resetting camera to default settings..." << endl;
490 | // camera.ResetCamera();
491 |
492 | // Initialize the camera and driver
493 | cout << "Initializing camera and driver..." << endl;
494 | camera.InitCamera(width, height, frameRate, onDemand, useTrigger, scaledWidth, scaledHeight, rotation, numImagesToRecord);
495 |
496 | cout << "Using Camera : " << camera.GetDeviceInfo().GetFriendlyName() << endl;
497 | cout << "Camera Area Of Interest : " << camera.GetWidth() << "x" << camera.GetHeight() << endl;
498 | cout << "Camera Speed : " << camera.GetFrameRate() << " fps" << endl;
499 | if (scaledWidth != -1 && scaledHeight != -1)
500 | cout << "Images will be scaled to : " << scaledWidth << "x" << scaledHeight << endl;
501 | if (rotation != -1)
502 | cout << "Images will be rotated : " << rotation << " degrees clockwise" << endl;
503 |
504 | // create a new pipeline to add elements too
505 | pipeline = gst_pipeline_new("pipeline");
506 |
507 | // prepare a handler (watcher) for messages from the pipeline
508 | bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));
509 | bus_watch_id = gst_bus_add_watch(bus, bus_call, loop);
510 | gst_object_unref(bus);
511 |
512 | // A pipeline needs a source element. The InstantCameraForAppSrc will create, configure, and provide an AppSrc which fits the camera.
513 | GstElement *source = camera.GetSource();
514 |
515 | // Build the rest of the pipeline based on the sample chosen.
516 | // The PipelineHelper will manage the configuration of GStreamer pipelines.
517 | // The pipeline helper can be expanded to create several kinds of pipelines
518 | // as these can depend heavily on the application and host capabilities.
519 | // Rescaling the image is optional. In this sample we do rescaling and rotation in the InstantCameraAppSrc.
520 | CPipelineHelper myPipelineHelper(pipeline, source);
521 |
522 | bool pipelineBuilt = false;
523 |
524 | if (display == true)
525 | pipelineBuilt = myPipelineHelper.build_pipeline_display();
526 | else if (h264stream == true)
527 | pipelineBuilt = myPipelineHelper.build_pipeline_h264stream(ipaddress.c_str());
528 | else if (h264multicast == true)
529 | pipelineBuilt = myPipelineHelper.build_pipeline_h264multicast(ipaddress.c_str());
530 | else if (h264file == true)
531 | pipelineBuilt = myPipelineHelper.build_pipeline_h264file(filename.c_str());
532 | else if (framebuffer == true)
533 | pipelineBuilt = myPipelineHelper.build_pipeline_framebuffer(fbdev.c_str());
534 | else if (parsestring == true)
535 | pipelineBuilt = myPipelineHelper.build_pipeline_parsestring(pipelineString.c_str());
536 |
537 | if (pipelineBuilt == false)
538 | {
539 | exitCode = -1;
540 | throw std::runtime_error("Pipeline building failed!");
541 | }
542 |
543 | // Start the camera and grab engine.
544 | if (camera.StartCamera() == false)
545 | {
546 | exitCode = -1;
547 | throw std::runtime_error("Could not start camera!");
548 | }
549 |
550 | // Start the pipeline.
551 | cout << "Starting pipeline..." << endl;
552 | gst_element_set_state(pipeline, GST_STATE_PLAYING);
553 |
554 | // run the main loop. When Ctrl+C is pressed, an EOS event will be sent
555 | // which will shutdown the pipeline in intHandler(), which will in turn quit the main loop.
556 | g_main_loop_run(loop);
557 |
558 | // clean up
559 | cout << "Stopping pipeline..." << endl;
560 | gst_element_set_state(pipeline, GST_STATE_NULL);
561 |
562 | camera.StopCamera();
563 | camera.CloseCamera();
564 |
565 | gst_object_unref(GST_OBJECT(pipeline));
566 | g_main_loop_unref(loop);
567 |
568 | exitCode = 0;
569 |
570 | }
571 | catch (GenICam::GenericException &e)
572 | {
573 | cerr << "An exception occured in main(): " << endl << e.GetDescription() << endl;
574 | exitCode = -1;
575 |
576 | }
577 | catch (std::exception &e)
578 | {
579 | cerr << "An exception occurred in main(): " << endl << e.what() << endl;
580 | exitCode = -1;
581 | }
582 |
583 | // Comment the following two lines to disable waiting on exit.
584 | cerr << endl << "Press Enter to exit." << endl;
585 | while (cin.get() != '\n');
586 |
587 | return exitCode;
588 | }
589 |
--------------------------------------------------------------------------------
/Samples/demopylongstreamer_jetson_performance/acA5472-17ucO_22860864.pfs:
--------------------------------------------------------------------------------
1 | # {05D8C294-F295-4dfb-9D01-096BD04049F4}
2 | # GenApi persistence file (version 3.1.0)
3 | # Device = Basler::UsbCameraParams -- Basler USB3Vision camera interface -- Device version = 1.0.0 -- Product GUID = 5a809e15-f447-480f-a21f-0fb7256b8400 -- Product version GUID = D37C6E20-54F3-437C-A49C-479F28C515DE
4 | ExposureAuto Off
5 | BalanceWhiteAuto Off
6 | GainAuto Off
7 | Width 4024
8 | Height 3648
9 | CenterX 1
10 | CenterY 1
11 | ReverseX 0
12 | ReverseY 0
13 | PixelFormat BayerRG8
14 | TestImageSelector Off
15 | GainSelector All
16 | Gain -0.00000
17 | GainSelector All
18 | BlackLevelSelector All
19 | BlackLevel 0.00000
20 | BlackLevelSelector All
21 | Gamma 1.00000
22 | DigitalShift 0
23 | RemoveParameterLimitSelector Gain
24 | RemoveParameterLimit 0
25 | RemoveParameterLimitSelector Gain
26 | LightSourcePreset Daylight5000K
27 | BalanceRatioSelector Red
28 | BalanceRatio 1.71875
29 | BalanceRatioSelector Green
30 | BalanceRatio 1.00000
31 | BalanceRatioSelector Blue
32 | BalanceRatio 1.90625
33 | BalanceRatioSelector Red
34 | ColorAdjustmentSelector Red
35 | ColorAdjustmentHue 0.12500
36 | ColorAdjustmentSelector Yellow
37 | ColorAdjustmentHue 0.46875
38 | ColorAdjustmentSelector Green
39 | ColorAdjustmentHue -0.56250
40 | ColorAdjustmentSelector Cyan
41 | ColorAdjustmentHue 0.37500
42 | ColorAdjustmentSelector Blue
43 | ColorAdjustmentHue 0.09375
44 | ColorAdjustmentSelector Magenta
45 | ColorAdjustmentHue 0.78125
46 | ColorAdjustmentSelector Red
47 | ColorAdjustmentSelector Red
48 | ColorAdjustmentSaturation 1.05469
49 | ColorAdjustmentSelector Yellow
50 | ColorAdjustmentSaturation 1.15625
51 | ColorAdjustmentSelector Green
52 | ColorAdjustmentSaturation 1.61719
53 | ColorAdjustmentSelector Cyan
54 | ColorAdjustmentSaturation 1.11719
55 | ColorAdjustmentSelector Blue
56 | ColorAdjustmentSaturation 0.85938
57 | ColorAdjustmentSelector Magenta
58 | ColorAdjustmentSaturation 0.75781
59 | ColorAdjustmentSelector Red
60 | ColorTransformationSelector RGBtoRGB
61 | ColorTransformationValueSelector Gain00
62 | ColorTransformationValue 1.18750
63 | ColorTransformationValueSelector Gain01
64 | ColorTransformationValue 0.46875
65 | ColorTransformationValueSelector Gain02
66 | ColorTransformationValue -0.65625
67 | ColorTransformationValueSelector Gain10
68 | ColorTransformationValue -0.37500
69 | ColorTransformationValueSelector Gain11
70 | ColorTransformationValue 2.28125
71 | ColorTransformationValueSelector Gain12
72 | ColorTransformationValue -0.90625
73 | ColorTransformationValueSelector Gain20
74 | ColorTransformationValue -0.12500
75 | ColorTransformationValueSelector Gain21
76 | ColorTransformationValue -0.12500
77 | ColorTransformationValueSelector Gain22
78 | ColorTransformationValue 1.25000
79 | ColorTransformationSelector RGBtoRGB
80 | ColorTransformationValueSelector Gain00
81 | VignettingCorrectionMode Off
82 | ShutterMode Rolling
83 | ExposureMode Timed
84 | ExposureTime 5005.0
85 | AcquisitionBurstFrameCount 1
86 | TriggerSelector FrameBurstStart
87 | TriggerMode Off
88 | TriggerSelector FrameStart
89 | TriggerMode Off
90 | TriggerSelector FrameStart
91 | TriggerSelector FrameBurstStart
92 | TriggerSource Line1
93 | TriggerSelector FrameStart
94 | TriggerSource Line1
95 | TriggerSelector FrameStart
96 | TriggerSelector FrameBurstStart
97 | TriggerActivation RisingEdge
98 | TriggerSelector FrameStart
99 | TriggerActivation RisingEdge
100 | TriggerSelector FrameStart
101 | TriggerDelay 0
102 | AcquisitionFrameRateEnable 0
103 | AcquisitionFrameRate 100.00000
104 | DeviceLinkSelector 0
105 | DeviceLinkThroughputLimitMode On
106 | DeviceLinkSelector 0
107 | DeviceLinkSelector 0
108 | DeviceLinkThroughputLimit 360000000
109 | DeviceLinkSelector 0
110 | ChunkSelector Gain
111 | ChunkEnable 0
112 | ChunkSelector ExposureTime
113 | ChunkEnable 0
114 | ChunkSelector Timestamp
115 | ChunkEnable 0
116 | ChunkSelector LineStatusAll
117 | ChunkEnable 0
118 | ChunkSelector CounterValue
119 | ChunkEnable 0
120 | ChunkSelector SequencerSetActive
121 | ChunkEnable 0
122 | ChunkSelector PayloadCRC16
123 | ChunkEnable 0
124 | ChunkSelector Timestamp
125 | ChunkModeActive 0
126 | AutoTargetBrightness 0.50196
127 | AutoFunctionProfile MinimizeGain
128 | AutoGainLowerLimit -0.00000
129 | AutoGainUpperLimit 27.04577
130 | AutoExposureTimeLowerLimit 52.0
131 | AutoExposureTimeUpperLimit 100009.0
132 | AutoFunctionROISelector ROI1
133 | AutoFunctionROIWidth 5472
134 | AutoFunctionROISelector ROI2
135 | AutoFunctionROIWidth 5472
136 | AutoFunctionROISelector ROI1
137 | AutoFunctionROISelector ROI1
138 | AutoFunctionROIHeight 3648
139 | AutoFunctionROISelector ROI2
140 | AutoFunctionROIHeight 3648
141 | AutoFunctionROISelector ROI1
142 | AutoFunctionROISelector ROI1
143 | AutoFunctionROIOffsetX 12
144 | AutoFunctionROISelector ROI2
145 | AutoFunctionROIOffsetX 12
146 | AutoFunctionROISelector ROI1
147 | AutoFunctionROISelector ROI1
148 | AutoFunctionROIOffsetY 12
149 | AutoFunctionROISelector ROI2
150 | AutoFunctionROIOffsetY 12
151 | AutoFunctionROISelector ROI1
152 | AutoFunctionROISelector ROI1
153 | AutoFunctionROIUseBrightness 1
154 | AutoFunctionROISelector ROI2
155 | AutoFunctionROIUseBrightness 0
156 | AutoFunctionROISelector ROI1
157 | AutoFunctionROISelector ROI1
158 | AutoFunctionROIUseWhiteBalance 0
159 | AutoFunctionROISelector ROI2
160 | AutoFunctionROIUseWhiteBalance 1
161 | AutoFunctionROISelector ROI1
162 | LUTSelector Luminance
163 | LUTEnable 0
164 | LUTSelector Luminance
165 | LUTSelector Luminance
166 | LUTValueAll 0x00000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003800000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000048000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000580000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000006800000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000078000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000880000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000009800000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000a800000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000b800000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000d800000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000e800000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000f80000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000801000000000000000000000000000000000000000000000000000000000000100100000000000000000000000000000000000000000000000000000000000018010000000000000000000000000000000000000000000000000000000000002001000000000000000000000000000000000000000000000000000000000000280100000000000000000000000000000000000000000000000000000000000030010000000000000000000000000000000000000000000000000000000000003801000000000000000000000000000000000000000000000000000000000000400100000000000000000000000000000000000000000000000000000000000048010000000000000000000000000000000000000000000000000000000000005001000000000000000000000000000000000000000000000000000000000000580100000000000000000000000000000000000000000000000000000000000060010000000000000000000000000000000000000000000000000000000000006801000000000000000000000000000000000000000000000000000000000000700100000000000000000000000000000000000000000000000000000000000078010000000000000000000000000000000000000000000000000000000000008001000000000000000000000000000000000000000000000000000000000000880100000000000000000000000000000000000000000000000000000000000090010000000000000000000000000000000000000000000000000000000000009801000000000000000000000000000000000000000000000000000000000000a001000000000000000000000000000000000000000000000000000000000000a801000000000000000000000000000000000000000000000000000000000000b001000000000000000000000000000000000000000000000000000000000000b801000000000000000000000000000000000000000000000000000000000000c001000000000000000000000000000000000000000000000000000000000000c801000000000000000000000000000000000000000000000000000000000000d001000000000000000000000000000000000000000000000000000000000000d801000000000000000000000000000000000000000000000000000000000000e001000000000000000000000000000000000000000000000000000000000000e801000000000000000000000000000000000000000000000000000000000000f001000000000000000000000000000000000000000000000000000000000000f80100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000802000000000000000000000000000000000000000000000000000000000000100200000000000000000000000000000000000000000000000000000000000018020000000000000000000000000000000000000000000000000000000000002002000000000000000000000000000000000000000000000000000000000000280200000000000000000000000000000000000000000000000000000000000030020000000000000000000000000000000000000000000000000000000000003802000000000000000000000000000000000000000000000000000000000000400200000000000000000000000000000000000000000000000000000000000048020000000000000000000000000000000000000000000000000000000000005002000000000000000000000000000000000000000000000000000000000000580200000000000000000000000000000000000000000000000000000000000060020000000000000000000000000000000000000000000000000000000000006802000000000000000000000000000000000000000000000000000000000000700200000000000000000000000000000000000000000000000000000000000078020000000000000000000000000000000000000000000000000000000000008002000000000000000000000000000000000000000000000000000000000000880200000000000000000000000000000000000000000000000000000000000090020000000000000000000000000000000000000000000000000000000000009802000000000000000000000000000000000000000000000000000000000000a002000000000000000000000000000000000000000000000000000000000000a802000000000000000000000000000000000000000000000000000000000000b002000000000000000000000000000000000000000000000000000000000000b802000000000000000000000000000000000000000000000000000000000000c002000000000000000000000000000000000000000000000000000000000000c802000000000000000000000000000000000000000000000000000000000000d002000000000000000000000000000000000000000000000000000000000000d802000000000000000000000000000000000000000000000000000000000000e002000000000000000000000000000000000000000000000000000000000000e802000000000000000000000000000000000000000000000000000000000000f002000000000000000000000000000000000000000000000000000000000000f80200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000803000000000000000000000000000000000000000000000000000000000000100300000000000000000000000000000000000000000000000000000000000018030000000000000000000000000000000000000000000000000000000000002003000000000000000000000000000000000000000000000000000000000000280300000000000000000000000000000000000000000000000000000000000030030000000000000000000000000000000000000000000000000000000000003803000000000000000000000000000000000000000000000000000000000000400300000000000000000000000000000000000000000000000000000000000048030000000000000000000000000000000000000000000000000000000000005003000000000000000000000000000000000000000000000000000000000000580300000000000000000000000000000000000000000000000000000000000060030000000000000000000000000000000000000000000000000000000000006803000000000000000000000000000000000000000000000000000000000000700300000000000000000000000000000000000000000000000000000000000078030000000000000000000000000000000000000000000000000000000000008003000000000000000000000000000000000000000000000000000000000000880300000000000000000000000000000000000000000000000000000000000090030000000000000000000000000000000000000000000000000000000000009803000000000000000000000000000000000000000000000000000000000000a003000000000000000000000000000000000000000000000000000000000000a803000000000000000000000000000000000000000000000000000000000000b003000000000000000000000000000000000000000000000000000000000000b803000000000000000000000000000000000000000000000000000000000000c003000000000000000000000000000000000000000000000000000000000000c803000000000000000000000000000000000000000000000000000000000000d003000000000000000000000000000000000000000000000000000000000000d803000000000000000000000000000000000000000000000000000000000000e003000000000000000000000000000000000000000000000000000000000000e803000000000000000000000000000000000000000000000000000000000000f003000000000000000000000000000000000000000000000000000000000000f80300000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000804000000000000000000000000000000000000000000000000000000000000100400000000000000000000000000000000000000000000000000000000000018040000000000000000000000000000000000000000000000000000000000002004000000000000000000000000000000000000000000000000000000000000280400000000000000000000000000000000000000000000000000000000000030040000000000000000000000000000000000000000000000000000000000003804000000000000000000000000000000000000000000000000000000000000400400000000000000000000000000000000000000000000000000000000000048040000000000000000000000000000000000000000000000000000000000005004000000000000000000000000000000000000000000000000000000000000580400000000000000000000000000000000000000000000000000000000000060040000000000000000000000000000000000000000000000000000000000006804000000000000000000000000000000000000000000000000000000000000700400000000000000000000000000000000000000000000000000000000000078040000000000000000000000000000000000000000000000000000000000008004000000000000000000000000000000000000000000000000000000000000880400000000000000000000000000000000000000000000000000000000000090040000000000000000000000000000000000000000000000000000000000009804000000000000000000000000000000000000000000000000000000000000a004000000000000000000000000000000000000000000000000000000000000a804000000000000000000000000000000000000000000000000000000000000b004000000000000000000000000000000000000000000000000000000000000b804000000000000000000000000000000000000000000000000000000000000c004000000000000000000000000000000000000000000000000000000000000c804000000000000000000000000000000000000000000000000000000000000d004000000000000000000000000000000000000000000000000000000000000d804000000000000000000000000000000000000000000000000000000000000e004000000000000000000000000000000000000000000000000000000000000e804000000000000000000000000000000000000000000000000000000000000f004000000000000000000000000000000000000000000000000000000000000f80400000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000805000000000000000000000000000000000000000000000000000000000000100500000000000000000000000000000000000000000000000000000000000018050000000000000000000000000000000000000000000000000000000000002005000000000000000000000000000000000000000000000000000000000000280500000000000000000000000000000000000000000000000000000000000030050000000000000000000000000000000000000000000000000000000000003805000000000000000000000000000000000000000000000000000000000000400500000000000000000000000000000000000000000000000000000000000048050000000000000000000000000000000000000000000000000000000000005005000000000000000000000000000000000000000000000000000000000000580500000000000000000000000000000000000000000000000000000000000060050000000000000000000000000000000000000000000000000000000000006805000000000000000000000000000000000000000000000000000000000000700500000000000000000000000000000000000000000000000000000000000078050000000000000000000000000000000000000000000000000000000000008005000000000000000000000000000000000000000000000000000000000000880500000000000000000000000000000000000000000000000000000000000090050000000000000000000000000000000000000000000000000000000000009805000000000000000000000000000000000000000000000000000000000000a005000000000000000000000000000000000000000000000000000000000000a805000000000000000000000000000000000000000000000000000000000000b005000000000000000000000000000000000000000000000000000000000000b805000000000000000000000000000000000000000000000000000000000000c005000000000000000000000000000000000000000000000000000000000000c805000000000000000000000000000000000000000000000000000000000000d005000000000000000000000000000000000000000000000000000000000000d805000000000000000000000000000000000000000000000000000000000000e005000000000000000000000000000000000000000000000000000000000000e805000000000000000000000000000000000000000000000000000000000000f005000000000000000000000000000000000000000000000000000000000000f80500000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000806000000000000000000000000000000000000000000000000000000000000100600000000000000000000000000000000000000000000000000000000000018060000000000000000000000000000000000000000000000000000000000002006000000000000000000000000000000000000000000000000000000000000280600000000000000000000000000000000000000000000000000000000000030060000000000000000000000000000000000000000000000000000000000003806000000000000000000000000000000000000000000000000000000000000400600000000000000000000000000000000000000000000000000000000000048060000000000000000000000000000000000000000000000000000000000005006000000000000000000000000000000000000000000000000000000000000580600000000000000000000000000000000000000000000000000000000000060060000000000000000000000000000000000000000000000000000000000006806000000000000000000000000000000000000000000000000000000000000700600000000000000000000000000000000000000000000000000000000000078060000000000000000000000000000000000000000000000000000000000008006000000000000000000000000000000000000000000000000000000000000880600000000000000000000000000000000000000000000000000000000000090060000000000000000000000000000000000000000000000000000000000009806000000000000000000000000000000000000000000000000000000000000a006000000000000000000000000000000000000000000000000000000000000a806000000000000000000000000000000000000000000000000000000000000b006000000000000000000000000000000000000000000000000000000000000b806000000000000000000000000000000000000000000000000000000000000c006000000000000000000000000000000000000000000000000000000000000c806000000000000000000000000000000000000000000000000000000000000d006000000000000000000000000000000000000000000000000000000000000d806000000000000000000000000000000000000000000000000000000000000e006000000000000000000000000000000000000000000000000000000000000e806000000000000000000000000000000000000000000000000000000000000f006000000000000000000000000000000000000000000000000000000000000f80600000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000807000000000000000000000000000000000000000000000000000000000000100700000000000000000000000000000000000000000000000000000000000018070000000000000000000000000000000000000000000000000000000000002007000000000000000000000000000000000000000000000000000000000000280700000000000000000000000000000000000000000000000000000000000030070000000000000000000000000000000000000000000000000000000000003807000000000000000000000000000000000000000000000000000000000000400700000000000000000000000000000000000000000000000000000000000048070000000000000000000000000000000000000000000000000000000000005007000000000000000000000000000000000000000000000000000000000000580700000000000000000000000000000000000000000000000000000000000060070000000000000000000000000000000000000000000000000000000000006807000000000000000000000000000000000000000000000000000000000000700700000000000000000000000000000000000000000000000000000000000078070000000000000000000000000000000000000000000000000000000000008007000000000000000000000000000000000000000000000000000000000000880700000000000000000000000000000000000000000000000000000000000090070000000000000000000000000000000000000000000000000000000000009807000000000000000000000000000000000000000000000000000000000000a007000000000000000000000000000000000000000000000000000000000000a807000000000000000000000000000000000000000000000000000000000000b007000000000000000000000000000000000000000000000000000000000000b807000000000000000000000000000000000000000000000000000000000000c007000000000000000000000000000000000000000000000000000000000000c807000000000000000000000000000000000000000000000000000000000000d007000000000000000000000000000000000000000000000000000000000000d807000000000000000000000000000000000000000000000000000000000000e007000000000000000000000000000000000000000000000000000000000000e807000000000000000000000000000000000000000000000000000000000000f007000000000000000000000000000000000000000000000000000000000000f80700000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000808000000000000000000000000000000000000000000000000000000000000100800000000000000000000000000000000000000000000000000000000000018080000000000000000000000000000000000000000000000000000000000002008000000000000000000000000000000000000000000000000000000000000280800000000000000000000000000000000000000000000000000000000000030080000000000000000000000000000000000000000000000000000000000003808000000000000000000000000000000000000000000000000000000000000400800000000000000000000000000000000000000000000000000000000000048080000000000000000000000000000000000000000000000000000000000005008000000000000000000000000000000000000000000000000000000000000580800000000000000000000000000000000000000000000000000000000000060080000000000000000000000000000000000000000000000000000000000006808000000000000000000000000000000000000000000000000000000000000700800000000000000000000000000000000000000000000000000000000000078080000000000000000000000000000000000000000000000000000000000008008000000000000000000000000000000000000000000000000000000000000880800000000000000000000000000000000000000000000000000000000000090080000000000000000000000000000000000000000000000000000000000009808000000000000000000000000000000000000000000000000000000000000a008000000000000000000000000000000000000000000000000000000000000a808000000000000000000000000000000000000000000000000000000000000b008000000000000000000000000000000000000000000000000000000000000b808000000000000000000000000000000000000000000000000000000000000c008000000000000000000000000000000000000000000000000000000000000c808000000000000000000000000000000000000000000000000000000000000d008000000000000000000000000000000000000000000000000000000000000d808000000000000000000000000000000000000000000000000000000000000e008000000000000000000000000000000000000000000000000000000000000e808000000000000000000000000000000000000000000000000000000000000f008000000000000000000000000000000000000000000000000000000000000f80800000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000809000000000000000000000000000000000000000000000000000000000000100900000000000000000000000000000000000000000000000000000000000018090000000000000000000000000000000000000000000000000000000000002009000000000000000000000000000000000000000000000000000000000000280900000000000000000000000000000000000000000000000000000000000030090000000000000000000000000000000000000000000000000000000000003809000000000000000000000000000000000000000000000000000000000000400900000000000000000000000000000000000000000000000000000000000048090000000000000000000000000000000000000000000000000000000000005009000000000000000000000000000000000000000000000000000000000000580900000000000000000000000000000000000000000000000000000000000060090000000000000000000000000000000000000000000000000000000000006809000000000000000000000000000000000000000000000000000000000000700900000000000000000000000000000000000000000000000000000000000078090000000000000000000000000000000000000000000000000000000000008009000000000000000000000000000000000000000000000000000000000000880900000000000000000000000000000000000000000000000000000000000090090000000000000000000000000000000000000000000000000000000000009809000000000000000000000000000000000000000000000000000000000000a009000000000000000000000000000000000000000000000000000000000000a809000000000000000000000000000000000000000000000000000000000000b009000000000000000000000000000000000000000000000000000000000000b809000000000000000000000000000000000000000000000000000000000000c009000000000000000000000000000000000000000000000000000000000000c809000000000000000000000000000000000000000000000000000000000000d009000000000000000000000000000000000000000000000000000000000000d809000000000000000000000000000000000000000000000000000000000000e009000000000000000000000000000000000000000000000000000000000000e809000000000000000000000000000000000000000000000000000000000000f009000000000000000000000000000000000000000000000000000000000000f809000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000080a000000000000000000000000000000000000000000000000000000000000100a000000000000000000000000000000000000000000000000000000000000180a000000000000000000000000000000000000000000000000000000000000200a000000000000000000000000000000000000000000000000000000000000280a000000000000000000000000000000000000000000000000000000000000300a000000000000000000000000000000000000000000000000000000000000380a000000000000000000000000000000000000000000000000000000000000400a000000000000000000000000000000000000000000000000000000000000480a000000000000000000000000000000000000000000000000000000000000500a000000000000000000000000000000000000000000000000000000000000580a000000000000000000000000000000000000000000000000000000000000600a000000000000000000000000000000000000000000000000000000000000680a000000000000000000000000000000000000000000000000000000000000700a000000000000000000000000000000000000000000000000000000000000780a000000000000000000000000000000000000000000000000000000000000800a000000000000000000000000000000000000000000000000000000000000880a000000000000000000000000000000000000000000000000000000000000900a000000000000000000000000000000000000000000000000000000000000980a000000000000000000000000000000000000000000000000000000000000a00a000000000000000000000000000000000000000000000000000000000000a80a000000000000000000000000000000000000000000000000000000000000b00a000000000000000000000000000000000000000000000000000000000000b80a000000000000000000000000000000000000000000000000000000000000c00a000000000000000000000000000000000000000000000000000000000000c80a000000000000000000000000000000000000000000000000000000000000d00a000000000000000000000000000000000000000000000000000000000000d80a000000000000000000000000000000000000000000000000000000000000e00a000000000000000000000000000000000000000000000000000000000000e80a000000000000000000000000000000000000000000000000000000000000f00a000000000000000000000000000000000000000000000000000000000000f80a000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000080b000000000000000000000000000000000000000000000000000000000000100b000000000000000000000000000000000000000000000000000000000000180b000000000000000000000000000000000000000000000000000000000000200b000000000000000000000000000000000000000000000000000000000000280b000000000000000000000000000000000000000000000000000000000000300b000000000000000000000000000000000000000000000000000000000000380b000000000000000000000000000000000000000000000000000000000000400b000000000000000000000000000000000000000000000000000000000000480b000000000000000000000000000000000000000000000000000000000000500b000000000000000000000000000000000000000000000000000000000000580b000000000000000000000000000000000000000000000000000000000000600b000000000000000000000000000000000000000000000000000000000000680b000000000000000000000000000000000000000000000000000000000000700b000000000000000000000000000000000000000000000000000000000000780b000000000000000000000000000000000000000000000000000000000000800b000000000000000000000000000000000000000000000000000000000000880b000000000000000000000000000000000000000000000000000000000000900b000000000000000000000000000000000000000000000000000000000000980b000000000000000000000000000000000000000000000000000000000000a00b000000000000000000000000000000000000000000000000000000000000a80b000000000000000000000000000000000000000000000000000000000000b00b000000000000000000000000000000000000000000000000000000000000b80b000000000000000000000000000000000000000000000000000000000000c00b000000000000000000000000000000000000000000000000000000000000c80b000000000000000000000000000000000000000000000000000000000000d00b000000000000000000000000000000000000000000000000000000000000d80b000000000000000000000000000000000000000000000000000000000000e00b000000000000000000000000000000000000000000000000000000000000e80b000000000000000000000000000000000000000000000000000000000000f00b000000000000000000000000000000000000000000000000000000000000f80b000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000080c000000000000000000000000000000000000000000000000000000000000100c000000000000000000000000000000000000000000000000000000000000180c000000000000000000000000000000000000000000000000000000000000200c000000000000000000000000000000000000000000000000000000000000280c000000000000000000000000000000000000000000000000000000000000300c000000000000000000000000000000000000000000000000000000000000380c000000000000000000000000000000000000000000000000000000000000400c000000000000000000000000000000000000000000000000000000000000480c000000000000000000000000000000000000000000000000000000000000500c000000000000000000000000000000000000000000000000000000000000580c000000000000000000000000000000000000000000000000000000000000600c000000000000000000000000000000000000000000000000000000000000680c000000000000000000000000000000000000000000000000000000000000700c000000000000000000000000000000000000000000000000000000000000780c000000000000000000000000000000000000000000000000000000000000800c000000000000000000000000000000000000000000000000000000000000880c000000000000000000000000000000000000000000000000000000000000900c000000000000000000000000000000000000000000000000000000000000980c000000000000000000000000000000000000000000000000000000000000a00c000000000000000000000000000000000000000000000000000000000000a80c000000000000000000000000000000000000000000000000000000000000b00c000000000000000000000000000000000000000000000000000000000000b80c000000000000000000000000000000000000000000000000000000000000c00c000000000000000000000000000000000000000000000000000000000000c80c000000000000000000000000000000000000000000000000000000000000d00c000000000000000000000000000000000000000000000000000000000000d80c000000000000000000000000000000000000000000000000000000000000e00c000000000000000000000000000000000000000000000000000000000000e80c000000000000000000000000000000000000000000000000000000000000f00c000000000000000000000000000000000000000000000000000000000000f80c000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000080d000000000000000000000000000000000000000000000000000000000000100d000000000000000000000000000000000000000000000000000000000000180d000000000000000000000000000000000000000000000000000000000000200d000000000000000000000000000000000000000000000000000000000000280d000000000000000000000000000000000000000000000000000000000000300d000000000000000000000000000000000000000000000000000000000000380d000000000000000000000000000000000000000000000000000000000000400d000000000000000000000000000000000000000000000000000000000000480d000000000000000000000000000000000000000000000000000000000000500d000000000000000000000000000000000000000000000000000000000000580d000000000000000000000000000000000000000000000000000000000000600d000000000000000000000000000000000000000000000000000000000000680d000000000000000000000000000000000000000000000000000000000000700d000000000000000000000000000000000000000000000000000000000000780d000000000000000000000000000000000000000000000000000000000000800d000000000000000000000000000000000000000000000000000000000000880d000000000000000000000000000000000000000000000000000000000000900d000000000000000000000000000000000000000000000000000000000000980d000000000000000000000000000000000000000000000000000000000000a00d000000000000000000000000000000000000000000000000000000000000a80d000000000000000000000000000000000000000000000000000000000000b00d000000000000000000000000000000000000000000000000000000000000b80d000000000000000000000000000000000000000000000000000000000000c00d000000000000000000000000000000000000000000000000000000000000c80d000000000000000000000000000000000000000000000000000000000000d00d000000000000000000000000000000000000000000000000000000000000d80d000000000000000000000000000000000000000000000000000000000000e00d000000000000000000000000000000000000000000000000000000000000e80d000000000000000000000000000000000000000000000000000000000000f00d000000000000000000000000000000000000000000000000000000000000f80d000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000080e000000000000000000000000000000000000000000000000000000000000100e000000000000000000000000000000000000000000000000000000000000180e000000000000000000000000000000000000000000000000000000000000200e000000000000000000000000000000000000000000000000000000000000280e000000000000000000000000000000000000000000000000000000000000300e000000000000000000000000000000000000000000000000000000000000380e000000000000000000000000000000000000000000000000000000000000400e000000000000000000000000000000000000000000000000000000000000480e000000000000000000000000000000000000000000000000000000000000500e000000000000000000000000000000000000000000000000000000000000580e000000000000000000000000000000000000000000000000000000000000600e000000000000000000000000000000000000000000000000000000000000680e000000000000000000000000000000000000000000000000000000000000700e000000000000000000000000000000000000000000000000000000000000780e000000000000000000000000000000000000000000000000000000000000800e000000000000000000000000000000000000000000000000000000000000880e000000000000000000000000000000000000000000000000000000000000900e000000000000000000000000000000000000000000000000000000000000980e000000000000000000000000000000000000000000000000000000000000a00e000000000000000000000000000000000000000000000000000000000000a80e000000000000000000000000000000000000000000000000000000000000b00e000000000000000000000000000000000000000000000000000000000000b80e000000000000000000000000000000000000000000000000000000000000c00e000000000000000000000000000000000000000000000000000000000000c80e000000000000000000000000000000000000000000000000000000000000d00e000000000000000000000000000000000000000000000000000000000000d80e000000000000000000000000000000000000000000000000000000000000e00e000000000000000000000000000000000000000000000000000000000000e80e000000000000000000000000000000000000000000000000000000000000f00e000000000000000000000000000000000000000000000000000000000000f80e000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000080f000000000000000000000000000000000000000000000000000000000000100f000000000000000000000000000000000000000000000000000000000000180f000000000000000000000000000000000000000000000000000000000000200f000000000000000000000000000000000000000000000000000000000000280f000000000000000000000000000000000000000000000000000000000000300f000000000000000000000000000000000000000000000000000000000000380f000000000000000000000000000000000000000000000000000000000000400f000000000000000000000000000000000000000000000000000000000000480f000000000000000000000000000000000000000000000000000000000000500f000000000000000000000000000000000000000000000000000000000000580f000000000000000000000000000000000000000000000000000000000000600f000000000000000000000000000000000000000000000000000000000000680f000000000000000000000000000000000000000000000000000000000000700f000000000000000000000000000000000000000000000000000000000000780f000000000000000000000000000000000000000000000000000000000000800f000000000000000000000000000000000000000000000000000000000000880f000000000000000000000000000000000000000000000000000000000000900f000000000000000000000000000000000000000000000000000000000000980f000000000000000000000000000000000000000000000000000000000000a00f000000000000000000000000000000000000000000000000000000000000a80f000000000000000000000000000000000000000000000000000000000000b00f000000000000000000000000000000000000000000000000000000000000b80f000000000000000000000000000000000000000000000000000000000000c00f000000000000000000000000000000000000000000000000000000000000c80f000000000000000000000000000000000000000000000000000000000000d00f000000000000000000000000000000000000000000000000000000000000d80f000000000000000000000000000000000000000000000000000000000000e00f000000000000000000000000000000000000000000000000000000000000e80f000000000000000000000000000000000000000000000000000000000000f00f000000000000000000000000000000000000000000000000000000000000f80f000000000000000000000000000000000000000000000000000000000000
167 | LUTSelector Luminance
168 | LineSelector Line1
169 | LineMode Input
170 | LineSelector Line2
171 | LineMode Output
172 | LineSelector Line3
173 | LineMode Input
174 | LineSelector Line4
175 | LineMode Input
176 | LineSelector Line1
177 | LineSelector Line2
178 | LineSource UserOutput1
179 | LineSelector Line1
180 | LineSelector Line1
181 | LineInverter 0
182 | LineSelector Line2
183 | LineInverter 0
184 | LineSelector Line3
185 | LineInverter 0
186 | LineSelector Line4
187 | LineInverter 0
188 | LineSelector Line1
189 | LineSelector Line1
190 | LineDebouncerTime 0.00000
191 | LineSelector Line3
192 | LineDebouncerTime 0.00000
193 | LineSelector Line4
194 | LineDebouncerTime 0.00000
195 | LineSelector Line1
196 | LineSelector Line2
197 | LineMinimumOutputPulseWidth 0.000
198 | LineSelector Line1
199 | UserOutputValueAll 0
200 | BslLightControlMode Off
201 | TimerSelector Timer1
202 | TimerDuration 10.0
203 | TimerSelector Timer1
204 | TimerSelector Timer1
205 | TimerDelay 0.0
206 | TimerSelector Timer1
207 | TimerSelector Timer1
208 | TimerTriggerSource ExposureStart
209 | TimerSelector Timer1
210 | CounterSelector Counter1
211 | CounterEventSource FrameStart
212 | CounterSelector Counter2
213 | CounterEventSource FrameStart
214 | CounterSelector Counter1
215 | CounterSelector Counter1
216 | CounterResetSource Off
217 | CounterSelector Counter2
218 | CounterResetSource Counter2End
219 | CounterSelector Counter1
220 | BslLightControlTriggerMode ExposureActive
221 | EventSelector ExposureEnd
222 | EventNotification Off
223 | EventSelector FrameBurstStart
224 | EventNotification Off
225 | EventSelector FrameStartOvertrigger
226 | EventNotification Off
227 | EventSelector FrameBurstStartOvertrigger
228 | EventNotification Off
229 | EventSelector CriticalTemperature
230 | EventNotification Off
231 | EventSelector OverTemperature
232 | EventNotification Off
233 | EventSelector FrameStartWait
234 | EventNotification Off
235 | EventSelector FrameBurstStartWait
236 | EventNotification Off
237 | EventSelector ExposureEnd
238 | UserDefinedValueSelector Value1
239 | UserDefinedValue 0
240 | UserDefinedValueSelector Value2
241 | UserDefinedValue 0
242 | UserDefinedValueSelector Value3
243 | UserDefinedValue 0
244 | UserDefinedValueSelector Value4
245 | UserDefinedValue 0
246 | UserDefinedValueSelector Value5
247 | UserDefinedValue 0
248 | UserDefinedValueSelector Value1
249 |
--------------------------------------------------------------------------------