├── 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 | --------------------------------------------------------------------------------