├── gst ├── GstreamerPipelines.h ├── GstPipelineWrapper.h ├── GstAppSinkPipeline.h ├── GstAppSrcPipeline.h ├── GstAppSrcPipeline.cpp ├── GstAppSinkPipeline.cpp └── GstPipelineWrapper.cpp ├── Main.cpp ├── Common.h ├── readme.md ├── .gitignore ├── opencv ├── OpenCVEffect.h ├── OpenCVFaceDect.h └── OpenCVFaceDect.cpp ├── makefile ├── OpenCVStream.h ├── PipeLines.h └── OpenCVStream.cpp /gst/GstreamerPipelines.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define LINK " ! " 6 | #define NEW_LINKAGE " " 7 | #define PAD "." 8 | 9 | #define APPSRC_NAME "appsrc_name" 10 | #define APPSINK_NAME "appsink_name" 11 | 12 | -------------------------------------------------------------------------------- /Main.cpp: -------------------------------------------------------------------------------- 1 | #include "Common.h" 2 | 3 | #include "OpenCVStream.h" 4 | 5 | int main(int argc, char* argv[]) 6 | { 7 | OpenCVStream* stream; 8 | 9 | stream = new OpenCVStream(); 10 | stream->StreamON(); 11 | 12 | std::cout << "Enter to leave!" << std::endl; 13 | 14 | getchar(); 15 | 16 | stream->StreamOFF(); 17 | 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /Common.h: -------------------------------------------------------------------------------- 1 | #ifndef _GST_OPENCV_H_ 2 | #define _GST_OPENCV_H_ 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | #include "gst/GstAppSinkPipeline.h" 16 | #include "gst/GstAppSrcPipeline.h" 17 | #include "gst/GstreamerPipelines.h" 18 | 19 | #include "opencv/OpenCVFaceDect.h" 20 | #include "opencv/OpenCVEffect.h" 21 | 22 | #endif -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ## Introduction 2 | 3 | Gstreamer + OpenCV Demo application. 4 | ZERO-COPY Optimization. 5 | Suitable for RockChip Platform. 6 | 7 | You could change pipeline by editing `pipelines.h`. 8 | 9 | pipeline: 10 | rtsp/video/camera ->(h264/mjpeg) -> mppvideodec -> (nv12) -> rga videoconvert -> (rgb) -> appsink 11 | appsrc ->(opencv process rgb) -> rkximagesink 12 | 13 | Assume: 14 | * rga = /dev/video0 15 | * camera = /dev/video1 16 | * videofile = /usr/local/test.mp4 17 | 18 | #### More in Blog 19 | 20 | Welcome Comments :-p 21 | 22 | http://blog.iotwrt.com/media/2017/08/23/opencv-gstreamer/ 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | aclocal.m4 2 | autom4te.cache 3 | config.h 4 | config.h.in 5 | config.h-new 6 | config.log 7 | config.status 8 | config.guess 9 | config.sub 10 | config.rpath 11 | config.guess.dh-orig 12 | config.sub.dh-orig 13 | configure 14 | gstreamer-rockchip.spec 15 | libtool 16 | stamp-h 17 | stamp-h.in 18 | stamp-h1 19 | gst-element-check-*.m4 20 | ltmain.sh 21 | missing 22 | mkinstalldirs 23 | compile 24 | install-sh 25 | depcomp 26 | autoregen.sh 27 | ABOUT-NLS 28 | /INSTALL 29 | _stdint.h 30 | gstreamer-rockchip-*.tar.* 31 | .dirstamp 32 | /*-libtool 33 | 34 | /m4 35 | 36 | .deps 37 | .libs 38 | *.lo 39 | *.la 40 | *.o 41 | Makefile.in 42 | Makefile 43 | *~ 44 | *.swp 45 | *.gc?? 46 | 47 | /m4 48 | 49 | tmp-orc.c 50 | *orc.h 51 | 52 | /tests/examples/player/ayamero-player 53 | /tests/examples/camera/camera-demo 54 | 55 | Build 56 | *.user 57 | *.suo 58 | *.ipch 59 | *.sdf 60 | *.opensdf 61 | *.DS_Store 62 | 63 | /test-driver 64 | *.log 65 | *.trs 66 | 67 | /build 68 | /subprojects 69 | -------------------------------------------------------------------------------- /opencv/OpenCVEffect.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd 3 | * Author: Jacob Chen 4 | * 5 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 6 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 7 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 8 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 9 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 10 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 11 | * SOFTWARE. 12 | */ 13 | 14 | #ifndef _OPENCV_EFFECT_H 15 | #define _OPENCV_EFFECT_H 16 | 17 | #include 18 | #include 19 | 20 | class OpenCVEffect { 21 | public: 22 | OpenCVEffect() { 23 | 24 | }; 25 | 26 | ~OpenCVEffect() { 27 | 28 | }; 29 | 30 | virtual void Process(void *framebuffer, int width, int height) { 31 | 32 | }; 33 | 34 | private: 35 | }; 36 | 37 | #endif -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | #CXX=g++ 2 | CXX=arm-linux-gnueabihf-g++ 3 | #export PKG_CONFIG_PATH=/usr/lib/arm-linux-gnueabihf/pkgconfig:$PKG_CONFIG_PATH 4 | 5 | GST_FLAGS=$(shell pkg-config --cflags --libs gstreamer-1.0) 6 | OPENCV_FLAGS=$(shell pkg-config --cflags --libs opencv) 7 | 8 | CFLAGS = $(GST_FLAGS) $(OPENCV_FLAGS) 9 | 10 | LIBS := -L/usr/lib/arm-linux-gnueabihf -lglib-2.0 -lgobject-2.0 -lopencv_imgproc -lopencv_highgui -lopencv_core -lopencv_calib3d 11 | LIBS += -lgstapp-1.0 -lgstreamer-1.0 -lgstbase-1.0 -lgobject-2.0 -lglib-2.0 -lgstvideo-1.0 -lgstallocators-1.0 12 | LIBS += -lboost_thread -lboost_system 13 | 14 | define all-cpp-files-under 15 | $(shell find $(1) -name "*."$(2) -and -not -name ".*" ) 16 | endef 17 | 18 | define all-subdir-cpp-files 19 | $(call all-cpp-files-under,.,"cpp") 20 | endef 21 | 22 | CPPSRCS = $(call all-subdir-cpp-files) 23 | 24 | CPPOBJS := $(CPPSRCS:.cpp=.o) 25 | 26 | all: gst_opencv 27 | 28 | gst_opencv: $(CPPOBJS) 29 | $(CXX) $(CFLAGS) $(CPPOBJS) -o gst_opencv $(LIBS) 30 | 31 | $(CPPOBJS) : %.o : %.cpp 32 | $(CXX) $(CFLAGS) -c $< -o $@ 33 | 34 | clean: 35 | rm -f opencv/*.o gst/*.o *.o gst_opencv 36 | -------------------------------------------------------------------------------- /OpenCVStream.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd 3 | * Author: Jacob Chen 4 | * 5 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 6 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 7 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 8 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 9 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 10 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 11 | * SOFTWARE. 12 | */ 13 | 14 | #ifndef _OPENCV_APPSINK_H 15 | #define _OPENCV_APPSINK_H 16 | 17 | #include "Common.h" 18 | 19 | class OpenCVStream{ 20 | public: 21 | OpenCVStream(); 22 | ~OpenCVStream(); 23 | 24 | void StreamON(); 25 | void StreamOFF(); 26 | 27 | void Process(); 28 | private: 29 | bool is_streaming__; 30 | GstAppSinkPipeline *sink_pipeline__; 31 | GstAppSrcPipeline *src_pipeline__; 32 | boost::thread process_thread__; 33 | boost::mutex state_mutex__; 34 | 35 | std::list effect_lists; 36 | }; 37 | 38 | #endif -------------------------------------------------------------------------------- /gst/GstPipelineWrapper.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 Samsung Electronics Corporation. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | class GstPipelineWrapper { 26 | public: 27 | GstPipelineWrapper(void); 28 | ~GstPipelineWrapper(void); 29 | 30 | void InitializePipelineWithString(std::string pipelineString); 31 | GstElement* GetElementByName(std::string element_name); 32 | 33 | void set_is_verbose(bool is_verbose); 34 | bool get_is_verbose() const; 35 | 36 | bool SetPipelineState(GstState state); 37 | GstState GetPipelineState(); 38 | 39 | private: 40 | bool is_verbose_; // default: false 41 | 42 | GstElement* pipeline_; 43 | GstBus* bus_; 44 | 45 | boost::thread g_main_loop_thread_; 46 | void RunningMainLoop(); 47 | 48 | void FreePipeline(); 49 | 50 | static bool GstMessageParser(GstBus* bus, GstMessage* msg, GstPipelineWrapper* pipeline); 51 | static void EnsureGstreamerInitialization(); 52 | }; 53 | -------------------------------------------------------------------------------- /opencv/OpenCVFaceDect.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd 3 | * Author: Jacob Chen 4 | * 5 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 6 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 7 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 8 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 9 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 10 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 11 | * SOFTWARE. 12 | */ 13 | 14 | #ifndef _OPENCV_FACEDECT_H 15 | #define _OPENCV_FACEDECT_H 16 | 17 | #include "OpenCVEffect.h" 18 | 19 | #include "opencv2/contrib/contrib.hpp" 20 | #include "opencv2/core/core.hpp" 21 | #include "opencv2/highgui/highgui.hpp" 22 | #include "opencv2/imgproc/imgproc.hpp" 23 | #include "opencv2/objdetect/objdetect.hpp" 24 | 25 | #include 26 | #include 27 | 28 | class OpenCVFaceDect : public OpenCVEffect { 29 | public: 30 | OpenCVFaceDect(); 31 | ~OpenCVFaceDect(); 32 | 33 | void Initialize(std::string cascade_path); 34 | void Process(void* framebuffer, int width, int height); 35 | void Draw(void *framebuffer, int width, int height); 36 | void Run(); 37 | 38 | void Update(std::vector &faces); 39 | 40 | private: 41 | cv::Mat gray__; 42 | cv::CascadeClassifier cascade__; 43 | boost::thread process_thread__; 44 | boost::mutex face_mutex__; 45 | boost::mutex thread_mutex__; 46 | double scale__; 47 | 48 | std::vector last_face__; 49 | }; 50 | 51 | #endif -------------------------------------------------------------------------------- /gst/GstAppSinkPipeline.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 Samsung Electronics Corporation. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | #include "GstPipelineWrapper.h" 20 | #include 21 | 22 | class GstAppSinkPipeline : public GstPipelineWrapper { 23 | public: 24 | GstAppSinkPipeline(); 25 | ~GstAppSinkPipeline(); 26 | 27 | void Initialize(std::string pipelineString); 28 | 29 | bool GetIsNewFrameAvailable(); 30 | bool GetLatestFrameBuffer(void** frameBuffer); 31 | void ReleaseFrameBuffer(); 32 | 33 | void set_is_streaming(bool is_streaming); 34 | 35 | bool GetLatestSample(GstSample** sample); 36 | 37 | private: 38 | bool is_streaming_; 39 | 40 | GstElement* appsink; 41 | 42 | boost::mutex bufferMutex; 43 | void ReceiveNewSample(); 44 | GstSample* retrievedBuffer; 45 | GstSample* currentBuffer; 46 | 47 | static void DestroyCallback(gpointer data); 48 | static void EndOfStreamCallback(GstAppSink* appsink, gpointer user_data); 49 | static GstFlowReturn NewPrerollCallback(GstAppSink* appsink, gpointer user_data); 50 | static GstFlowReturn NewSampleCallback(GstAppSink* appsink, gpointer user_data); 51 | }; 52 | -------------------------------------------------------------------------------- /gst/GstAppSrcPipeline.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 Samsung Electronics Corporation. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | #include "GstPipelineWrapper.h" 20 | #include 21 | 22 | class GstAppSrcPipeline : public GstPipelineWrapper { 23 | public: 24 | GstAppSrcPipeline(); 25 | ~GstAppSrcPipeline(void); 26 | 27 | void Initialize(std::string pipelineString); 28 | 29 | bool GetNeedsData() const; 30 | bool SendFrame(unsigned char* buffer, unsigned int bufferSize); 31 | bool SendBUF(GstBuffer* buffer); 32 | 33 | private: 34 | boost::mutex pushBufferFlagMutex; 35 | 36 | // Callbacks for various signals 37 | static void NeedDataCallback(GstAppSrc* appsrc, guint length, gpointer user_data); 38 | static void EnoughDataCallback(GstAppSrc* appsrc, gpointer user_data); 39 | static gboolean SeekDataCallback(GstAppSrc* appsrc, guint64 offset, gpointer user_data); 40 | 41 | static bool ParseMessageCallback(GstBus* bus, GstMessage* msg, GstAppSrcPipeline* multicaster); 42 | 43 | static void DestroyCallback(GstAppSrcPipeline* multicaster); 44 | 45 | GstElement* appsrc; 46 | 47 | void FreePipeline(); 48 | 49 | bool needsData; 50 | }; 51 | -------------------------------------------------------------------------------- /PipeLines.h: -------------------------------------------------------------------------------- 1 | #ifndef _PIPELINE_H 2 | #define _PIPELINE_H 3 | 4 | #define TEST_VIDEO 5 | //#define TEST_RTSP 6 | //#define TEST_CAMERA 7 | 8 | #ifndef TEST_CAMERA 9 | static std::string CreateAppSinkPipeline() 10 | { 11 | std::stringstream pipelineString; 12 | 13 | pipelineString 14 | #ifdef TEST_RTSP 15 | << "rtsp://192.168.31.163:554/" 16 | << LINK 17 | #elif defined TEST_VIDEO 18 | << "filesrc location=/usr/local/test.mp4" 19 | << LINK 20 | << "qtdemux" 21 | << LINK 22 | #endif 23 | << "h264parse" 24 | << LINK 25 | << "mppvideodec" 26 | << LINK 27 | << "video/x-raw,format=(string)NV12" 28 | << LINK 29 | << "rgaconvert output-io-mode=dmabuf-import capture-io-mode=dmabuf vpu-stride=true" 30 | << LINK 31 | << "video/x-raw,format=BGR,width=(int)1920,height=(int)1080" 32 | << LINK 33 | << "appsink caps=video/x-raw,format=BGR name=" 34 | << APPSINK_NAME; 35 | 36 | return pipelineString.str(); 37 | } 38 | #else 39 | static std::string CreateAppSinkPipeline() 40 | { 41 | std::stringstream pipelineString; 42 | 43 | pipelineString 44 | << "v4l2src device=/dev/video1" 45 | << LINK 46 | << "mppvideodec" 47 | << LINK 48 | << "rgaconvert output-io-mode=dmabuf-import capture-io-mode=dmabuf" 49 | << LINK 50 | << "video/x-raw,format=(string)BGR,width=(int)1920,height=(int)1080,framerate=(fraction)30/1" 51 | << LINK 52 | << "appsink name=" 53 | << APPSINK_NAME; 54 | 55 | return pipelineString.str(); 56 | } 57 | #endif 58 | 59 | static std::string CreateAppSrcPipeline() 60 | { 61 | std::stringstream pipelineString; 62 | 63 | pipelineString 64 | << "appsrc caps=video/x-raw,format=(string)BGR,width=(int)1920,height=(int)1080,framerate=(fraction)30/1 " 65 | "block=true name=" 66 | << APPSRC_NAME 67 | << LINK 68 | << "rkximagesink sync=false"; 69 | 70 | return pipelineString.str(); 71 | } 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /gst/GstAppSrcPipeline.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 Samsung Electronics Corporation. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "GstAppSrcPipeline.h" 18 | #include "GstreamerPipelines.h" 19 | #include 20 | 21 | GstAppSrcPipeline::GstAppSrcPipeline() 22 | : needsData(false) 23 | { 24 | } 25 | 26 | GstAppSrcPipeline::~GstAppSrcPipeline(void) {} 27 | 28 | void GstAppSrcPipeline::Initialize(std::string pipelineString) 29 | { 30 | GstPipelineWrapper::InitializePipelineWithString(pipelineString); 31 | 32 | appsrc = GstPipelineWrapper::GetElementByName(APPSRC_NAME); 33 | 34 | GstAppSrcCallbacks appsrcCallbacks; 35 | 36 | appsrcCallbacks.need_data = GstAppSrcPipeline::NeedDataCallback; 37 | appsrcCallbacks.enough_data = GstAppSrcPipeline::EnoughDataCallback; 38 | appsrcCallbacks.seek_data = GstAppSrcPipeline::SeekDataCallback; 39 | 40 | gst_app_src_set_callbacks(GST_APP_SRC(appsrc), &appsrcCallbacks, this, (GDestroyNotify)GstAppSrcPipeline::DestroyCallback); 41 | gst_app_src_set_max_bytes(GST_APP_SRC(appsrc), 0); 42 | } 43 | 44 | bool GstAppSrcPipeline::GetNeedsData() const 45 | { 46 | boost::mutex::scoped_lock(pushBufferFlagMutex); 47 | return needsData; 48 | } 49 | 50 | bool GstAppSrcPipeline::SendFrame(unsigned char* frameBuffer, unsigned int bufferSize) 51 | { 52 | boost::mutex::scoped_lock(pushBufferFlagMutex); 53 | if (!needsData) { 54 | std::cout << "CHANGED\n"; 55 | return false; 56 | } 57 | GstBuffer* buffer = gst_buffer_new_wrapped_full(GST_MEMORY_FLAG_READONLY, frameBuffer, bufferSize, 0, bufferSize, this, (GDestroyNotify)GstAppSrcPipeline::DestroyCallback); 58 | ; 59 | if (buffer) { 60 | if (needsData) 61 | GstFlowReturn ret = gst_app_src_push_buffer((GstAppSrc*)appsrc, buffer); // buffer released automatically 62 | } 63 | 64 | return true; 65 | } 66 | 67 | bool GstAppSrcPipeline::SendBUF(GstBuffer* buffer) 68 | { 69 | boost::mutex::scoped_lock(pushBufferFlagMutex); 70 | if (!needsData) { 71 | std::cout << "CHANGED\n"; 72 | return false; 73 | } 74 | 75 | if (buffer) { 76 | if (needsData) 77 | GstFlowReturn ret = gst_app_src_push_buffer((GstAppSrc*)appsrc, buffer); // buffer released automatically 78 | } 79 | 80 | return true; 81 | } 82 | 83 | void GstAppSrcPipeline::DestroyCallback(GstAppSrcPipeline* multicaster) 84 | { 85 | // DO NOTHING 86 | } 87 | 88 | void GstAppSrcPipeline::NeedDataCallback(GstAppSrc* appsrc, guint length, gpointer user_data) 89 | { 90 | GstAppSrcPipeline* multicaster = (GstAppSrcPipeline*)user_data; 91 | boost::mutex::scoped_lock(multicaster->pushBufferFlagMutex); 92 | multicaster->needsData = true; 93 | } 94 | 95 | void GstAppSrcPipeline::EnoughDataCallback(GstAppSrc* appsrc, gpointer user_data) 96 | { 97 | GstAppSrcPipeline* multicaster = (GstAppSrcPipeline*)user_data; 98 | boost::mutex::scoped_lock(multicaster->pushBufferFlagMutex); 99 | multicaster->needsData = false; 100 | } 101 | 102 | gboolean GstAppSrcPipeline::SeekDataCallback(GstAppSrc* appsrc, guint64 offset, gpointer user_data) 103 | { 104 | std::cout << "SEEK DATA CALLBACK: SHOULD NEVER BE HERE!\n"; 105 | return false; 106 | } 107 | -------------------------------------------------------------------------------- /opencv/OpenCVFaceDect.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd 3 | * Author: Jacob Chen 4 | * 5 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 6 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 7 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 8 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 9 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 10 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 11 | * SOFTWARE. 12 | */ 13 | 14 | #include "OpenCVFaceDect.h" 15 | 16 | using namespace cv; 17 | 18 | OpenCVFaceDect::OpenCVFaceDect() 19 | { 20 | scale__ = 8; 21 | 22 | ocl::setBinaryPath("./blobs/"); 23 | } 24 | 25 | OpenCVFaceDect::~OpenCVFaceDect() 26 | { 27 | } 28 | 29 | void OpenCVFaceDect::Initialize(std::string cascade_path) 30 | { 31 | if (!cascade__.load(cascade_path)) { 32 | std::cout << "ERROR: Load cascade failed" << std::endl; 33 | } 34 | } 35 | 36 | void OpenCVFaceDect::Update(std::vector &faces) 37 | { 38 | boost::lock_guard guard(face_mutex__); 39 | last_face__ = faces; 40 | } 41 | 42 | void OpenCVFaceDect::Run() 43 | { 44 | boost::lock_guard guard(thread_mutex__); 45 | Mat smallImg(cvRound(gray__.rows / scale__), cvRound(gray__.cols / scale__), CV_8UC1); 46 | std::vector faces; 47 | double t = (double)cvGetTickCount(); 48 | 49 | // scale to small picture 50 | resize(gray__, smallImg, smallImg.size(), 0, 0, INTER_LINEAR); 51 | equalizeHist(smallImg, smallImg); 52 | 53 | cascade__.detectMultiScale(smallImg, faces, 1.1, 54 | 1, 0 | CV_HAAR_SCALE_IMAGE, Size(10, 10), Size(0, 0)); 55 | 56 | t = (double)cvGetTickCount() - t; 57 | printf("detection time = %g ms\n", t / ((double)cvGetTickFrequency() * 1000.)); 58 | 59 | Update(faces); 60 | } 61 | 62 | void OpenCVFaceDect::Process(void* framebuffer, int width, int height) 63 | { 64 | Mat frame(height, width, CV_8UC3, (char*)framebuffer, Mat::AUTO_STEP); 65 | 66 | if(thread_mutex__.try_lock()) { 67 | cvtColor(frame, gray__, CV_BGR2GRAY); 68 | process_thread__ = boost::thread(&OpenCVFaceDect::Run, this); 69 | thread_mutex__.unlock(); 70 | } 71 | 72 | Draw(framebuffer, width, height); 73 | } 74 | 75 | void OpenCVFaceDect::Draw(void *framebuffer, int width, int height) 76 | { 77 | boost::lock_guard guard(face_mutex__); 78 | Mat frame(height, width, CV_8UC3, (char*)framebuffer, Mat::AUTO_STEP); 79 | int i; 80 | 81 | const static Scalar colors[] = { CV_RGB(0, 0, 255), 82 | CV_RGB(0, 128, 255), 83 | CV_RGB(0, 255, 255), 84 | CV_RGB(0, 255, 0), 85 | CV_RGB(255, 128, 0), 86 | CV_RGB(255, 255, 0), 87 | CV_RGB(255, 0, 0), 88 | CV_RGB(255, 0, 255) }; 89 | 90 | for (std::vector::const_iterator r = last_face__.begin(); r != last_face__.end(); r++, i++) { 91 | std::vector nestedObjects; 92 | Point center; 93 | Scalar color = colors[i % 8]; 94 | int radius; 95 | 96 | double aspect_ratio = (double)r->width / r->height; 97 | if (0.75 < aspect_ratio && aspect_ratio < 1.3) { 98 | center.x = cvRound((r->x + r->width * 0.5) * scale__); 99 | center.y = cvRound((r->y + r->height * 0.5) * scale__); 100 | radius = cvRound((r->width + r->height) * 0.25 * scale__); 101 | circle(frame, center, radius, color, 3, 8, 0); 102 | } else 103 | rectangle(frame, cvPoint(cvRound(r->x * scale__), cvRound(r->y * scale__)), 104 | cvPoint(cvRound((r->x + r->width - 1) * scale__), cvRound((r->y + r->height - 1) * scale__)), 105 | color, 3, 8, 0); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /OpenCVStream.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd 3 | * Author: Jacob Chen 4 | * 5 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 6 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 7 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 8 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 9 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 10 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 11 | * SOFTWARE. 12 | */ 13 | 14 | #include "OpenCVStream.h" 15 | #include "PipeLines.h" 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | OpenCVStream::OpenCVStream() 22 | { 23 | is_streaming__ = false; 24 | 25 | OpenCVFaceDect* face_dect = new OpenCVFaceDect(); 26 | face_dect->Initialize("./blobs/haarcascade_frontalface_alt.xml"); 27 | 28 | effect_lists.push_back(face_dect); 29 | } 30 | 31 | OpenCVStream::~OpenCVStream() 32 | { 33 | if (is_streaming__) { 34 | StreamOFF(); 35 | } 36 | } 37 | 38 | void OpenCVStream::StreamON() 39 | { 40 | boost::lock_guard guard(state_mutex__); 41 | 42 | if (is_streaming__) { 43 | return; 44 | } 45 | 46 | sink_pipeline__ = new GstAppSinkPipeline(); 47 | sink_pipeline__->Initialize(CreateAppSinkPipeline()); 48 | sink_pipeline__->set_is_streaming(true); 49 | sink_pipeline__->SetPipelineState(GST_STATE_PLAYING); 50 | 51 | src_pipeline__ = new GstAppSrcPipeline(); 52 | src_pipeline__->Initialize(CreateAppSrcPipeline()); 53 | src_pipeline__->SetPipelineState(GST_STATE_PLAYING); 54 | 55 | process_thread__ = boost::thread(&OpenCVStream::Process, this); 56 | is_streaming__ = true; 57 | } 58 | 59 | void OpenCVStream::StreamOFF() 60 | { 61 | boost::lock_guard guard(state_mutex__); 62 | 63 | if (!is_streaming__) { 64 | return; 65 | } 66 | 67 | is_streaming__ = false; 68 | process_thread__.join(); 69 | src_pipeline__->SetPipelineState(GST_STATE_PAUSED); 70 | sink_pipeline__->SetPipelineState(GST_STATE_PAUSED); 71 | sink_pipeline__->set_is_streaming(false); 72 | delete src_pipeline__; 73 | delete sink_pipeline__; 74 | } 75 | 76 | void OpenCVStream::Process() 77 | { 78 | GstSample* sample; 79 | GstMapInfo map; 80 | GstStructure* s; 81 | GstBuffer* buffer; 82 | GstCaps* caps; 83 | GstMemory* mem; 84 | int height, width, size; 85 | int fd; 86 | void* map_data; 87 | 88 | while (is_streaming__) { 89 | if (sink_pipeline__->GetIsNewFrameAvailable()) { 90 | sink_pipeline__->GetLatestSample(&sample); 91 | 92 | caps = gst_sample_get_caps(sample); 93 | buffer = gst_sample_get_buffer(sample); 94 | s = gst_caps_get_structure(caps, 0); 95 | gst_structure_get_int(s, "height", &height); 96 | gst_structure_get_int(s, "width", &width); 97 | 98 | size = gst_buffer_get_size(buffer); 99 | /* Since gstreamer don't support map buffer to write, 100 | * we have to use mmap directly 101 | */ 102 | mem = gst_buffer_peek_memory(buffer, 0); 103 | fd = gst_dmabuf_memory_get_fd(mem); 104 | map_data = mmap64(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 105 | 106 | std::list::iterator itor = effect_lists.begin(); 107 | while (itor != effect_lists.end()) { 108 | /* assume BGR */ 109 | (*itor)->Process((void*)map_data, width, height); 110 | 111 | itor++; 112 | } 113 | 114 | munmap(map_data, size); 115 | /* will auto released */ 116 | gst_buffer_ref(buffer); 117 | src_pipeline__->SendBUF(buffer); 118 | sink_pipeline__->ReleaseFrameBuffer(); 119 | /* g_print("%s\n", gst_caps_to_string(caps)); */ 120 | } 121 | } 122 | } 123 | 124 | //gst_sample_ref(&sample); 125 | //gst_sample_unref(&sample); -------------------------------------------------------------------------------- /gst/GstAppSinkPipeline.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 Samsung Electronics Corporation. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include 18 | 19 | #include "GstAppSinkPipeline.h" 20 | #include "GstreamerPipelines.h" 21 | 22 | GstAppSinkPipeline::GstAppSinkPipeline() 23 | : retrievedBuffer(0) 24 | , currentBuffer(0) 25 | , is_streaming_(true) 26 | { 27 | 28 | } 29 | 30 | GstAppSinkPipeline::~GstAppSinkPipeline() 31 | { 32 | 33 | } 34 | 35 | void GstAppSinkPipeline::Initialize(std::string pipelineString) 36 | { 37 | GstPipelineWrapper::InitializePipelineWithString(pipelineString); 38 | 39 | // setup appsink 40 | appsink = GstPipelineWrapper::GetElementByName(APPSINK_NAME); 41 | GstAppSinkCallbacks appsinkCallbacks; 42 | appsinkCallbacks.new_preroll = &GstAppSinkPipeline::NewPrerollCallback; 43 | appsinkCallbacks.new_sample = &GstAppSinkPipeline::NewSampleCallback; 44 | appsinkCallbacks.eos = &GstAppSinkPipeline::EndOfStreamCallback; 45 | 46 | gst_app_sink_set_drop(GST_APP_SINK(appsink), true); 47 | gst_app_sink_set_max_buffers(GST_APP_SINK(appsink), 1); 48 | //gst_app_sink_set_emit_signals (GST_APP_SINK(appsink), true); 49 | gst_app_sink_set_callbacks(GST_APP_SINK(appsink), &appsinkCallbacks, this, (GDestroyNotify)GstAppSinkPipeline::DestroyCallback); 50 | } 51 | 52 | void GstAppSinkPipeline::EndOfStreamCallback(GstAppSink* appsink, gpointer user_data) 53 | { 54 | 55 | } 56 | 57 | GstFlowReturn GstAppSinkPipeline::NewPrerollCallback(GstAppSink* appsink, gpointer user_data) 58 | { 59 | GstSample* sample = gst_app_sink_pull_preroll(appsink); 60 | gst_sample_unref(sample); 61 | return GST_FLOW_OK; 62 | } 63 | 64 | GstFlowReturn GstAppSinkPipeline::NewSampleCallback(GstAppSink* appsink, gpointer user_data) 65 | { 66 | ((GstAppSinkPipeline*)user_data)->ReceiveNewSample(); 67 | return GST_FLOW_OK; 68 | } 69 | 70 | void GstAppSinkPipeline::DestroyCallback(gpointer user_data) 71 | { 72 | std::cout << "DESTROY" << std::endl; 73 | } 74 | 75 | void GstAppSinkPipeline::set_is_streaming(bool is_streaming) 76 | { 77 | boost::lock_guard guard(bufferMutex); 78 | is_streaming_ = is_streaming; 79 | 80 | if (is_streaming_) 81 | return; 82 | 83 | if (currentBuffer) 84 | gst_sample_unref(currentBuffer); 85 | currentBuffer = 0; 86 | } 87 | 88 | void GstAppSinkPipeline::ReceiveNewSample() 89 | { 90 | if (!is_streaming_) 91 | return; 92 | 93 | GstSample* sample = gst_app_sink_pull_sample(GST_APP_SINK(appsink)); 94 | 95 | if (sample) { 96 | boost::lock_guard guard(bufferMutex); 97 | if (currentBuffer != 0) // release if not empty 98 | { 99 | gst_sample_unref(currentBuffer); 100 | } 101 | 102 | currentBuffer = sample; 103 | } 104 | } 105 | 106 | void GstAppSinkPipeline::ReleaseFrameBuffer() 107 | { 108 | boost::lock_guard guard(bufferMutex); 109 | if (retrievedBuffer) 110 | gst_sample_unref(retrievedBuffer); 111 | retrievedBuffer = 0; 112 | } 113 | 114 | bool GstAppSinkPipeline::GetIsNewFrameAvailable() 115 | { 116 | boost::lock_guard guard(bufferMutex); 117 | return ((retrievedBuffer == 0) && (currentBuffer != 0)); 118 | } 119 | 120 | bool GstAppSinkPipeline::GetLatestFrameBuffer(void** frameBuffer) 121 | { 122 | bool retrieving = false; 123 | 124 | boost::lock_guard guard(bufferMutex); 125 | if (retrievedBuffer == 0) { 126 | if (currentBuffer != 0) { 127 | retrievedBuffer = currentBuffer; 128 | currentBuffer = 0; 129 | retrieving = true; 130 | } 131 | } 132 | 133 | if (retrieving) { 134 | 135 | GstBuffer* buffer; 136 | GstMapInfo map; 137 | 138 | buffer = gst_sample_get_buffer(retrievedBuffer); 139 | 140 | if (buffer) { 141 | gst_buffer_map(buffer, &map, GST_MAP_READ); 142 | (*frameBuffer) = map.data; 143 | gst_buffer_unmap(buffer, &map); 144 | 145 | } else 146 | return false; 147 | } 148 | 149 | return true; 150 | } 151 | 152 | bool GstAppSinkPipeline::GetLatestSample(GstSample** sample) 153 | { 154 | boost::lock_guard guard(bufferMutex); 155 | if (retrievedBuffer == 0) { 156 | if (currentBuffer != 0) { 157 | retrievedBuffer = currentBuffer; 158 | currentBuffer = 0; 159 | (*sample) = retrievedBuffer; 160 | } 161 | } else { 162 | (*sample) = NULL; 163 | return false; 164 | } 165 | 166 | return true; 167 | } 168 | -------------------------------------------------------------------------------- /gst/GstPipelineWrapper.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 Samsung Electronics Corporation. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "GstPipelineWrapper.h" 18 | 19 | GstPipelineWrapper::GstPipelineWrapper(void) 20 | : is_verbose_(false) 21 | { 22 | EnsureGstreamerInitialization(); 23 | } 24 | 25 | GstPipelineWrapper::~GstPipelineWrapper(void) 26 | { 27 | FreePipeline(); 28 | } 29 | 30 | void GstPipelineWrapper::InitializePipelineWithString(std::string pipelineString) 31 | { 32 | /// Init pipeline using string 33 | GError* err = 0; 34 | pipeline_ = gst_parse_launch(pipelineString.c_str(), &err); 35 | 36 | /// Get bus and add message parser 37 | bus_ = gst_pipeline_get_bus(GST_PIPELINE(pipeline_)); 38 | gst_bus_add_watch(bus_, (GstBusFunc)GstPipelineWrapper::GstMessageParser, this); 39 | 40 | /// Run the main loop to receive messages from bus 41 | g_main_loop_thread_ = boost::thread(&GstPipelineWrapper::RunningMainLoop, this); 42 | } 43 | 44 | GstElement* GstPipelineWrapper::GetElementByName(std::string element_name) 45 | { 46 | return gst_bin_get_by_name(GST_BIN(pipeline_), element_name.c_str()); 47 | } 48 | 49 | bool GstPipelineWrapper::SetPipelineState(GstState state) 50 | { 51 | GstStateChangeReturn ret = gst_element_set_state(pipeline_, state); 52 | 53 | if (ret == GST_STATE_CHANGE_FAILURE) { 54 | g_printerr("Unable to set the pipeline to the playing state"); 55 | gst_object_unref(pipeline_); 56 | return false; 57 | } 58 | return true; 59 | } 60 | 61 | GstState GstPipelineWrapper::GetPipelineState() 62 | { 63 | GstState current_state, pending_state; 64 | GstStateChangeReturn ret = gst_element_get_state(pipeline_, ¤t_state, &pending_state, GST_CLOCK_TIME_NONE); 65 | return current_state; 66 | } 67 | 68 | void GstPipelineWrapper::RunningMainLoop() 69 | { 70 | GMainLoop* loop = g_main_loop_new(NULL, FALSE); 71 | g_main_loop_run(loop); 72 | } 73 | 74 | bool GstPipelineWrapper::GstMessageParser(GstBus* bus, GstMessage* msg, GstPipelineWrapper* pipeline) 75 | { 76 | if (!pipeline->get_is_verbose()) 77 | return true; 78 | 79 | if (msg != NULL) { 80 | GError* err = 0; 81 | gchar* debug_info = 0; 82 | 83 | switch (GST_MESSAGE_TYPE(msg)) { 84 | case GST_MESSAGE_ERROR: 85 | gst_message_parse_error(msg, &err, &debug_info); 86 | g_printerr("Error received from element %s: %s\n", GST_OBJECT_NAME(msg->src), err->message); 87 | g_printerr("Debugging information: %s\n", debug_info ? debug_info : "none"); 88 | g_clear_error(&err); 89 | g_free(debug_info); 90 | break; 91 | 92 | case GST_MESSAGE_WARNING: 93 | gst_message_parse_warning(msg, &err, &debug_info); 94 | g_printerr("Warning received from element %s: %s\n", GST_OBJECT_NAME(msg->src), err->message); 95 | g_printerr("Debugging information: %s\n", debug_info ? debug_info : "none"); 96 | g_clear_error(&err); 97 | g_free(debug_info); 98 | break; 99 | 100 | case GST_MESSAGE_INFO: 101 | gst_message_parse_info(msg, &err, &debug_info); 102 | g_printerr("Info received from element %s: %s\n", GST_OBJECT_NAME(msg->src), err->message); 103 | g_printerr("Debugging information: %s\n", debug_info ? debug_info : "none"); 104 | g_clear_error(&err); 105 | g_free(debug_info); 106 | break; 107 | 108 | case GST_MESSAGE_EOS: 109 | g_print("End-Of-Stream reached.\n"); 110 | break; 111 | 112 | case GST_MESSAGE_STATE_CHANGED: 113 | GstState old_state, new_state; 114 | gst_message_parse_state_changed(msg, &old_state, &new_state, 0); 115 | g_print("Element %s changed state from %s to %s.\n", GST_OBJECT_NAME(msg->src), gst_element_state_get_name(old_state), gst_element_state_get_name(new_state)); 116 | break; 117 | 118 | case GST_MESSAGE_QOS: 119 | break; 120 | 121 | case GST_MESSAGE_STREAM_STATUS: 122 | 123 | GstStreamStatusType stream_status_type; 124 | GstElement* owner; 125 | const gchar* stream_status_type_string; 126 | gst_message_parse_stream_status(msg, &stream_status_type, &owner); 127 | 128 | switch (stream_status_type) { 129 | case GST_STREAM_STATUS_TYPE_CREATE: 130 | stream_status_type_string = "CREATE"; 131 | break; 132 | case GST_STREAM_STATUS_TYPE_ENTER: 133 | stream_status_type_string = "ENTER"; 134 | break; 135 | case GST_STREAM_STATUS_TYPE_LEAVE: 136 | stream_status_type_string = "LEAVE"; 137 | break; 138 | case GST_STREAM_STATUS_TYPE_DESTROY: 139 | stream_status_type_string = "DESTROY"; 140 | break; 141 | 142 | case GST_STREAM_STATUS_TYPE_START: 143 | stream_status_type_string = "START"; 144 | break; 145 | case GST_STREAM_STATUS_TYPE_PAUSE: 146 | stream_status_type_string = "PAUSE"; 147 | break; 148 | case GST_STREAM_STATUS_TYPE_STOP: 149 | stream_status_type_string = "STOP"; 150 | break; 151 | } 152 | 153 | g_printerr("STREAM STATUS received from element %s: %s\n", GST_OBJECT_NAME(owner), stream_status_type_string); 154 | //g_free (stream_status_type_string); 155 | break; 156 | 157 | default: 158 | g_printerr("Unparsed message received of type: %s\n", gst_message_type_get_name(GST_MESSAGE_TYPE(msg))); 159 | break; 160 | } 161 | } 162 | return true; 163 | } 164 | 165 | void GstPipelineWrapper::EnsureGstreamerInitialization() 166 | { 167 | if (!gst_is_initialized()) { 168 | // int argc = 0; 169 | // char** argv = NULL; 170 | 171 | int argc = 0; 172 | char** argv = new char*[2]; 173 | 174 | argv[argc++] = "--gst-version"; 175 | argv[argc++] = "--gst-debug-level=1"; 176 | 177 | gst_init(&argc, &argv); 178 | 179 | delete argv; 180 | 181 | // get and display GST version 182 | { 183 | guint major = 0; 184 | guint minor = 0; 185 | guint micro = 0; 186 | guint nano = 0; 187 | 188 | gst_version(&major, &minor, µ, &nano); 189 | 190 | std::cout << "GStreamer V" << major << "." << minor << "." << micro << "." << nano << std::endl; 191 | } 192 | } 193 | } 194 | 195 | void GstPipelineWrapper::FreePipeline() 196 | { 197 | gst_element_set_state(pipeline_, GST_STATE_NULL); 198 | gst_object_unref(bus_); 199 | gst_object_unref(pipeline_); 200 | } 201 | 202 | void GstPipelineWrapper::set_is_verbose(bool is_verbose) { is_verbose = is_verbose; }; 203 | bool GstPipelineWrapper::get_is_verbose() const { return is_verbose_; } 204 | --------------------------------------------------------------------------------