├── .DS_Store ├── pyapi ├── __pycache__ │ ├── gst_rtsp_client_api.cpython-37.pyc │ ├── gst_rtsp_client_api.cpython-38.pyc │ └── gst_rtsp_client_api.cpython-39.pyc └── gst_rtsp_client_api.py ├── .vscode └── settings.json ├── LICENSE ├── README.md ├── multip_thread_rtsp_one.py ├── CMakeLists.txt ├── include └── gst_rtsp_client.h ├── multip_thread_rtsp.py ├── src ├── setup.cpp └── gst_rtsp_client.cpp ├── multip_thread_rtsp_rknn.py └── test └── c_test_main_rtsp.cpp /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuyuliang/gst_rtsp_client/HEAD/.DS_Store -------------------------------------------------------------------------------- /pyapi/__pycache__/gst_rtsp_client_api.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuyuliang/gst_rtsp_client/HEAD/pyapi/__pycache__/gst_rtsp_client_api.cpython-37.pyc -------------------------------------------------------------------------------- /pyapi/__pycache__/gst_rtsp_client_api.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuyuliang/gst_rtsp_client/HEAD/pyapi/__pycache__/gst_rtsp_client_api.cpython-38.pyc -------------------------------------------------------------------------------- /pyapi/__pycache__/gst_rtsp_client_api.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuyuliang/gst_rtsp_client/HEAD/pyapi/__pycache__/gst_rtsp_client_api.cpython-39.pyc -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "*.tcc": "cpp", 4 | "string": "cpp", 5 | "unordered_map": "cpp", 6 | "string_view": "cpp", 7 | "array": "cpp" 8 | } 9 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2021 SteveZ (https://github.com/zhuyuliang) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gstreamer_rtsp_client 2 | ## gst rtsp _ rk3399prod 3 | ### rtspsrc->decodebin(mppvideodec)->tee->queue->appsink->rga 4 | #### 优点: 5 | * 1.多线程rtsp调用 6 | * 2.c/c++开发 7 | * 3.cpython调用 8 | * 4.支持 h265/h264 9 | * 5.支持分辨率 10 | * 640 * 480 11 | * 1280 * 720 12 | * 1920 * 1080 13 | * 2560 * 1440 14 | * 3840 * 2160 15 | #### 目前尽支持测试大华摄像头和海康威视摄像头直连 16 | #### rockchip平台依赖环境 17 | * 1.[Mpp](https://t.rock-chips.com/forum.php?mod=viewthread&tid=336&highlight=mpp) 18 | * 2.[Rga](https://t.rock-chips.com/forum.php?mod=viewthread&tid=333&highlight=rga) 19 | * 3.[Gstreamer_plugin](https://github.com/zhuyuliang/gstreamer-rockchip-1) 20 | * 4.[Gstreamer_plugin_extra](https://github.com/zhuyuliang/gstreamer-rockchip-extra) 21 | 22 | #### jeston nx 6.4.2 23 | * [branch jetpacklib](https://github.com/zhuyuliang/gst_rtsp_client/tree/jetpacklib) 24 | 25 | --- 26 | ## 待处理 27 | 28 | - [x] 测试用例测试 29 | - [ ] 添加DRM显示 30 | - [x] gst rtsp _ (deepstream)/tensorrt .. wait .. (rtspsrc decodebin(Gst-nvvideo4linux2) tee queue Gst-nvvideoconvert appsink (GST-nvinfer Gst-nvtracker)) 31 | -------------------------------------------------------------------------------- /multip_thread_rtsp_one.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3.6 2 | from concurrent.futures import thread 3 | import os 4 | import time 5 | import threading 6 | import cv2 7 | import numpy as np 8 | 9 | from multiprocessing import Lock, Process, Condition, Queue 10 | 11 | import pyapi.gst_rtsp_client_api as rtspclient 12 | 13 | # from ctypes import * 14 | 15 | def func_rtspdisplay(index,url, usr, pwd): 16 | 17 | width = 1920 18 | height = 1080 19 | 20 | resize_width = 0 21 | resize_height = 0 22 | 23 | # c_url = create_string_buffer(url.encode('utf-8'), len(url)) 24 | # ret = rtspclient.createRtspClient(index,url) 25 | 26 | while(1) : 27 | ret1 = rtspclient.isConnect(index) 28 | print("id %d ret = %d",index, ret1) 29 | time.sleep(0.1) 30 | if (ret1 == 1): 31 | status, img, img_resize = rtspclient.mread_rga(index,width,height,resize_width,resize_height) 32 | # status, img, img_resize = rtspclient.mread_opencv(index) 33 | if status == 1: 34 | print(type(img)) 35 | print(img.shape) 36 | # img = cv2.resize(img,(1920,1080,3)) 37 | # img = cv2.UMat(height,width,cv2.CV_8UC3,img) 38 | # img = cv2.UMat(height,width,cv2.CV_8UC3,ret2.frame) 39 | # cv2.imshow("name", ret2.frame) 40 | # cv2.waitKey(0) 41 | pass 42 | # time.sleep(0.1) 43 | # cv2.imwrite('a' + str(index) +'.jpg',ret2.frame) 44 | # cv2.imwrite('a640' + str(index) +'.jpg',ret2.frame_resize) 45 | else: 46 | print("python disconnect") 47 | elif (ret1 == 2): 48 | print("destoryRtspClient") 49 | rtspclient.createRtspClient(index,url) 50 | 51 | print('# End of Thread %d' % (index)) 52 | 53 | 54 | if __name__ == '__main__': 55 | os.system('iptables -F') # Disable Firewall 56 | 57 | #gl = toy.output.createGLDrmDisplay(toy.DisplayPort.HDMI_A) 58 | #idx0 = gl.add_view(0, 180, 640, 360) 59 | # idx1 = gl.add_view(640, 180, 640, 360) 60 | # idx2 = gl.add_view(1280, 180, 640, 360) 61 | # idx3 = gl.add_view(0, 540, 640, 360) 62 | # idx4 = gl.add_view(640, 540, 640, 360) 63 | # idx5 = gl.add_view(1280, 540, 640, 360) 64 | 65 | t5 = Process(target=func_rtspdisplay, args = (6, "rtsp://admin:qwer1234@192.168.2.52:554/Streaming/Channels/1", "admin", "qwer1234")) 66 | 67 | t5.start() 68 | 69 | t5.join() 70 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | # project name 3 | project(vscode_cmake_gstreamer_learn) 4 | 5 | set(CMAKE_C_COMPILER gcc) 6 | set(CMAKE_CXX_COMPILER g++) 7 | 8 | set(CMAKE_CXX_STANDARD 11) 9 | set(CMAKE_CXX_STANDARD_REQUIRED TRUE) 10 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pthread -g -lX11") 11 | 12 | MESSAGE(STATUS "operation system is ${CMAKE_SYSTEM}") 13 | MESSAGE(STATUS "CMAKE_SYSTEM_NAME is ${CMAKE_SYSTEM}") 14 | IF (CMAKE_SYSTEM_NAME MATCHES "Linux") 15 | MESSAGE(STATUS "current platform: Linux ") 16 | ELSEIF (CMAKE_SYSTEM_NAME MATCHES "Windows") 17 | MESSAGE(STATUS "current platform: Windows") 18 | ELSEIF (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") 19 | MESSAGE(STATUS "current platform: FreeBSD") 20 | ELSE () 21 | MESSAGE(STATUS "other platform: ${CMAKE_SYSTEM_NAME}") 22 | ENDIF (CMAKE_SYSTEM_NAME MATCHES "Linux") 23 | 24 | if(${CMAKE_SYSTEM} MATCHES "Linux-4.9.140-tegra") 25 | message("On TEGRA PLATFORM.") 26 | add_definitions(-DPLATFORM_TEGRA) 27 | set(SYS_USR_LIB /usr/lib/aarch64-linux-gnu) 28 | set(SYS_LIB /lib/aarch64-linux-gnu) 29 | set(DS_LIB /opt/nvidia/deepstream/deepstream-4.0/lib) 30 | else() 31 | # message("On X86 PLATFORM.") 32 | # set(SYS_USR_LIB /usr/lib/x86_64-linux-gnu) 33 | # set(SYS_LIB /lib/x86_64-linux-gnu) 34 | 35 | message("On aarch64 PLATFORM.") 36 | set(SYS_USR_LIB /usr/lib/aarch64-linux-gnu) 37 | set(SYS_LIB /lib/aarch64-linux-gnu) 38 | endif() 39 | 40 | # gst 41 | include_directories( 42 | /usr/includes 43 | /usr/include/gstreamer-1.0 44 | /usr/lib/aarch64-linux-gnu/gstreamer-1.0 45 | /usr/lib/gstreamer-1.0 46 | /usr/include/glib-2.0 47 | ${SYS_USR_LIB}/glib-2.0/include 48 | /usr/include/orc-0.4 49 | /usr/include/rockchip 50 | /usr/local/include/opencv4/opencv2 51 | /usr/local/include 52 | /usr/local/lib/aarch64-linux-gnu 53 | ${CMAKE_CURRENT_SOURCE_DIR}/include 54 | # ${CMAKE_CURRENT_SOURCE_DIR}/rga/librga 55 | # /home/teamhd/librga-main/include 56 | # rk3588 57 | /usr/local/include 58 | /usr/local/lib/aarch64-linux-gnu 59 | /usr/local/include/opencv4 60 | ) 61 | 62 | link_libraries( 63 | ${SYS_USR_LIB}/libgstreamer-1.0.so.0 64 | ${SYS_USR_LIB}/libgobject-2.0.so.0 65 | ${SYS_USR_LIB}/libglib-2.0.so.0 66 | ${SYS_USR_LIB}/libgstbase-1.0.so.0 67 | ${SYS_USR_LIB}/libgstvideo-1.0.so.0 68 | ${SYS_USR_LIB}/libgstapp-1.0.so.0 69 | ${SYS_LIB}/libc.so.6 70 | ${SYS_LIB}/libdl.so.2 71 | ${SYS_LIB}/libpthread.so.0 72 | ${SYS_USR_LIB}/libgmodule-2.0.so.0 73 | ${SYS_LIB}/libm.so.6 74 | # rk3399prod 75 | # ${SYS_USR_LIB}/libffi.so.6 76 | ${SYS_LIB}/libpcre.so.3 77 | # ${CMAKE_CURRENT_SOURCE_DIR}/rga/librga/build/librga.so 78 | /usr/lib/aarch64-linux-gnu/librga.so 79 | #/home/teamhd/librga-main/libs/Linux/gcc-aarch64/librga.so 80 | # rk3588 81 | ${SYS_USR_LIB}/libffi.so 82 | ) 83 | 84 | # debug 85 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g") 86 | 87 | find_package(CURL REQUIRED) 88 | find_package(OpenCV REQUIRED) 89 | set(link_libs curl pthread opencv_core opencv_highgui opencv_imgcodecs) 90 | 91 | set(SRC_LIST ./test/c_test_main_rtsp.cpp 92 | ./src/gst_rtsp_client.cpp) 93 | 94 | add_executable (main_gst_rtsp_ ${SRC_LIST}) 95 | target_link_libraries(main_gst_rtsp_ ${link_libs}) 96 | add_library(RtspClientLib SHARED ./include/gst_rtsp_client.h ./src/gst_rtsp_client.cpp ./src/setup.cpp) 97 | -------------------------------------------------------------------------------- /include/gst_rtsp_client.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by steve 21-09-16 3 | // 4 | // gstreamer如何接入RTSP流(IP摄像头) 1. h264/h265 2. udp tcp 5 | // rtspsrc decodebin(h265/264 mppvideodec) tee queue appsink -> rga 6 | 7 | #ifndef SQ_RTSP_H 8 | #define SQ_RTSP_H 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | // gst 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | #include 39 | #include 40 | #include 41 | 42 | // rga 43 | #include 44 | #include 45 | #include 46 | #include 47 | 48 | // opencv2 49 | #include 50 | #include 51 | #include 52 | #include 53 | 54 | // gst log config 55 | //GST_DEBUG_CATEGORY_STATIC (rk_appsink_debug); 56 | //#define GST_CAT_DEFAULT rk_appsink_debug 57 | 58 | //rga 59 | #define SRC_FORMAT RK_FORMAT_YCrCb_420_SP 60 | #define DST_FORMAT RK_FORMAT_RGB_888 61 | 62 | #define STATUS_INIT 0 63 | #define STATUS_CONNECTED 1 64 | #define STATUS_DISCONNECT 2 65 | #define STATUS_CONNECTING 3 66 | 67 | #define DEFAULT_CONN_MODE 0 68 | #define TCP_CONN_MODE 1 69 | #define UDP_CONN_MODE 2 70 | 71 | inline static const char * 72 | yesno (int yes) 73 | { 74 | return yes ? "yes" : "no"; 75 | } 76 | 77 | struct MppFrameData { 78 | std::string data; 79 | int size; 80 | }; 81 | 82 | struct FrameData { 83 | char * data = NULL; 84 | int size; 85 | int width; 86 | int height; 87 | int isRun = STATUS_INIT; 88 | // inference scale 89 | int size_resize; 90 | char * data_resize = NULL; 91 | }; 92 | 93 | // CustomData 94 | struct CustomData { 95 | GMainLoop *loop = NULL; 96 | GstElement *pipeline = NULL; 97 | GstElement *rtspsrc = NULL; 98 | GstElement *decode = NULL; 99 | GstElement *tee = NULL; 100 | GstElement *queue_appsink = NULL; 101 | GstElement *appsink = NULL; 102 | 103 | GstBus *bus = NULL; 104 | 105 | gint format; 106 | GstVideoInfo info; 107 | int last_time_width = 0; 108 | int last_time_hetight = 0; 109 | 110 | unsigned frame; 111 | 112 | char * m_RtspUri = NULL; 113 | int m_Id = 0; 114 | int conn_Mode = DEFAULT_CONN_MODE; 115 | int isRun = STATUS_INIT; 116 | 117 | // rga buf 118 | char * dst_buf = NULL; 119 | char * dst_output_buf = NULL; 120 | char * dst_resize_output_buf = NULL; 121 | 122 | // inference resize 640 123 | char * dst_resize_output_resize_buf = NULL; 124 | char * dst_output_resize_buf = NULL; 125 | }; 126 | 127 | class RtspClient { 128 | public: 129 | 130 | RtspClient(); 131 | ~RtspClient(); 132 | 133 | bool enable(int id, const char * url, int conn_mode); 134 | void disable(); 135 | int isConnect(); 136 | bool changeURL(int id, const char* url, int conn_mode); 137 | bool reConnect(int id); 138 | 139 | struct FrameData * read_Opencv(); 140 | struct FrameData * read_Rga(int width, int height, int resize_width, int resize_height); 141 | 142 | private: 143 | pthread_t m_thread; 144 | struct CustomData m_data; 145 | 146 | }; 147 | 148 | #endif //SQ_RTSP_H 149 | -------------------------------------------------------------------------------- /multip_thread_rtsp.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3.6 2 | import os 3 | import time 4 | import threading 5 | import cv2 6 | import numpy as np 7 | import pyapi.gst_rtsp_client_api as rtspclient 8 | from multiprocessing import Lock, Process, Condition, Queue 9 | 10 | 11 | # def callback_frame(a,b): 12 | # print("callback") 13 | # pass 14 | 15 | # functype = CFUNCTYPE(c_int,c_int) 16 | # c_calback_python = functype(callback_frame) 17 | # client.register_py_to_c(c_calback_python) 18 | 19 | def func_rtspdisplay(index,url, usr, pwd): 20 | 21 | width = 1920 22 | height = 1080 23 | 24 | resize_width = 0 25 | resize_height = 0 26 | 27 | rtspclient.createRtspClient(index,url) 28 | 29 | time.sleep(0.5) 30 | 31 | while(1) : 32 | ret1 = rtspclient.isConnect(index) 33 | print("id %d ret = %d",index, ret1) 34 | # time.sleep(0.1) 35 | if (ret1 == 1): 36 | # print("id %d mread",index) 37 | # status, img, img_resize = rtspclient.mread_rga(index,width,height,resize_width,resize_height) 38 | status, img, img_resize = rtspclient.mread_opencv(index) 39 | if status == 1: 40 | print(type(img)) 41 | # print(img.shape) 42 | # print("success %d, %d",index,ret1) 43 | # time.sleep(1) 44 | # cv2.imwrite('a' + str(index) +'.jpg',img) 45 | pass 46 | else: 47 | print("python mread_rga disconnect") 48 | del status, img, img_resize 49 | # status, img, img_size = rtspclient.mread_opencv(index) 50 | # if status == 1: 51 | # img = cv2.UMat.get(img) 52 | # # cv2.imwrite('a' + str(index) +'.jpg',img) 53 | # else: 54 | # print("python mread_opencv disconnect") 55 | # del status, img, img_size 56 | else: 57 | time.sleep(3) 58 | rtspclient.reConnect(index) 59 | print("status %d, %d",index,ret1) 60 | 61 | print('# End of Thread %d' % (index)) 62 | 63 | 64 | if __name__ == '__main__': 65 | os.system('iptables -F') # Disable Firewall 66 | 67 | #gl = toy.output.createGLDrmDisplay(toy.DisplayPort.HDMI_A) 68 | #idx0 = gl.add_view(0, 180, 640, 360) 69 | # idx1 = gl.add_view(640, 180, 640, 360) 70 | # idx2 = gl.add_view(1280, 180, 640, 360) 71 | # idx3 = gl.add_view(0, 540, 640, 360) 72 | # idx4 = gl.add_view(640, 540, 640, 360) 73 | # idx5 = gl.add_view(1280, 540, 640, 360) 74 | 75 | t0 = threading.Thread(target=func_rtspdisplay, args = (1,"rtsp://admin:qwer1234@192.168.2.51:554/Streaming/Channels/1", "admin", "shangqu2020")) 76 | t1 = threading.Thread(target=func_rtspdisplay, args = (2,"rtsp://admin:qwer1234@192.168.2.52:554/Streaming/Channels/1", "admin", "shangqu2020")) 77 | t2 = threading.Thread(target=func_rtspdisplay, args = (3,"rtsp://admin:qwer1234@192.168.2.55:554/Streaming/Channels/1", "admin", "shangqu2020")) 78 | t3 = threading.Thread(target=func_rtspdisplay, args = (4,'rtsp://admin:qwer1234@192.168.2.54:554/Streaming/Channels/1', "admin", "shangqu2020")) 79 | t4 = threading.Thread(target=func_rtspdisplay, args = (5,"rtsp://admin:qwer1234@192.168.2.55:554/Streaming/Channels/1", "admin", "shangqu2020")) 80 | t5 = threading.Thread(target=func_rtspdisplay, args = (6, "rtsp://admin:qwer1234@192.168.2.54:554/Streaming/Channels/1", "admin", "shangqu2020")) 81 | t6 = threading.Thread(target=func_rtspdisplay, args = (7, "rtsp://admin:qwer1234@192.168.2.51:554/Streaming/Channels/1", "admin", "shangqu2020")) 82 | t7 = threading.Thread(target=func_rtspdisplay, args = (8, "rtsp://admin:qwer1234@192.168.2.52:554/Streaming/Channels/1", "admin", "shangqu2020")) 83 | 84 | t0.start() 85 | t1.start() 86 | t2.start() 87 | t3.start() 88 | t4.start() 89 | t5.start() 90 | t6.start() 91 | t7.start() 92 | 93 | t0.join() 94 | t1.join() 95 | t2.join() 96 | t3.join() 97 | t4.join() 98 | t5.join() 99 | t6.join() 100 | t7.join() 101 | -------------------------------------------------------------------------------- /pyapi/gst_rtsp_client_api.py: -------------------------------------------------------------------------------- 1 | from ctypes import * 2 | import numpy as np 3 | import time 4 | import cv2 5 | 6 | # 加载库文件 7 | rtsp_client = cdll.LoadLibrary("build/libRtspClientLib.so") 8 | 9 | DEFAULT_CONN_MODE = 0 10 | TCP_CONN_MODE = 1 11 | UDP_CONN_MODE = 2 12 | 13 | # 创建RTSP实例 14 | def createRtspClient( id, url, mode = TCP_CONN_MODE): 15 | print("python createRtspClient id = %d %s",id, url) 16 | isSuccess = rtsp_client.createRtspClient( id,url.encode(),mode) 17 | return isSuccess 18 | 19 | # 销毁全部RTSP连接 20 | def destoryRtspClientAll(): 21 | isSuccess = rtsp_client.destoryRtspClientAll() 22 | return isSuccess 23 | 24 | # # 销毁指定ID的RTSP连接 25 | # def destoryRtspClient( id): 26 | # isSuccess = rtsp_client.destoryRtspClient(id) 27 | # return isSuccess 28 | 29 | # 是否连接 30 | # STATUS_INIT 0 初始化状态 31 | # STATUS_CONNECTED 已连接 32 | # STATUS_DISCONNECT 已断开 33 | # STATUS_CONNECTING 连接中 34 | def isConnect( id): 35 | return rtsp_client.isConnect(id) 36 | 37 | def changeURL( id, url, mode = TCP_CONN_MODE): 38 | print("python changeURL id = %d %s",id, url) 39 | isSuccess = rtsp_client.changeURL( id,url.encode(),mode) 40 | return isSuccess 41 | 42 | def reConnect( id): 43 | print("python reConnect id = %d %s",id) 44 | isSuccess = rtsp_client.reConnect( id) 45 | return isSuccess 46 | 47 | # 同步读取帧数据 48 | # return 状态:ret, 设定的原图:img, 裁剪图片: img_resize 49 | def mread_rga( id, width, height, resize_width, resize_height): 50 | origin_img_size = width * height * 3 51 | c_pbuf = create_string_buffer(''.encode('utf-8'), origin_img_size) 52 | resize_img_size, c_pbuf_resize = None, None 53 | if resize_width > 0 and resize_height > 0: 54 | resize_img_size = resize_width * resize_height * 3 55 | c_pbuf_resize = create_string_buffer(''.encode('utf-8'),resize_img_size) 56 | ret = rtsp_client.mRead_Rga(id, width, height, resize_width, resize_height, c_pbuf, origin_img_size, c_pbuf_resize, resize_img_size) 57 | img_origin, img_resize = None, None 58 | if ret == 1: 59 | img_origin = np.frombuffer(string_at(c_pbuf, origin_img_size), dtype=np.uint8).reshape(height, width, 3) 60 | if resize_width > 0 and resize_height > 0: 61 | img_resize = np.frombuffer(string_at(c_pbuf_resize, resize_img_size), dtype=np.uint8).reshape(resize_width, resize_height, 3) 62 | del origin_img_size, c_pbuf 63 | del resize_img_size, c_pbuf_resize 64 | return ret, img_origin, img_resize 65 | 66 | # 同步读取帧数据 67 | # return 状态:ret, 设定的原图:img umat 68 | def mread_opencv(id): 69 | source_width = c_int(0) 70 | source_height = c_int(0) 71 | source_size = c_int(0) 72 | c_pbuf = create_string_buffer(''.encode('utf-8'), 99999999) 73 | pBuf = c_char_p(addressof(c_pbuf)) 74 | ret = rtsp_client.mRead_Python(id, byref(source_width), 75 | byref(source_height), byref(source_size), pointer(c_pbuf)) 76 | img_resize, img_size = None, None 77 | if ret == 1: 78 | img_origin = np.frombuffer(string_at(c_pbuf, source_size), dtype=np.uint8).reshape(int(source_height.value * 3 / 2), source_width.value) 79 | yuvNV12 = cv2.UMat(img_origin) 80 | # rgb24 = cv2.Mat(source_height.value, source_width.value , cv2.CV_8UC3) 81 | rgb24 = cv2.cvtColor(yuvNV12 , cv2.COLOR_YUV2BGR_NV12) 82 | # h265 256bit 1920 * 1080 == 2304 * 1080 83 | if (source_size.value == 3732480 or source_size.value == 4976640 ): 84 | img_resize = cv2.UMat(rgb24,[0,1080],[0,1920]) 85 | img_size = [1920, 1080] 86 | # h264 16bit 1920 * 1080 == 1920 * 1088 87 | elif (source_size.value == 3133440 or source_size.value == 4177920 ): 88 | img_resize = cv2.UMat(rgb24,[0,1080],[0,1920]) 89 | img_size = [1920, 1080] 90 | # h265 2560 * 1440 256 2816 1584 91 | elif (source_size.value == 6082560 or source_size.value == 8110080): 92 | img_resize = cv2.UMat(rgb24,[0,1440],[0,2560]) 93 | img_size = [2560, 1440] 94 | # h265 640*480 768 * 480 95 | elif (source_size.value == 552960): 96 | img_resize = cv2.UMat(rgb24,[0,480],[0,640]) 97 | img_size = [640, 480] 98 | else: 99 | # h265 h264 100 | # supoort 1280*720 3840*2160 101 | img_resize = rgb24 102 | img_size = [source_width.value, source_height.value] 103 | return ret, img_resize, img_size -------------------------------------------------------------------------------- /src/setup.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace std; 11 | 12 | #define FAIL 0; 13 | #define SUCCESS 1; 14 | 15 | unordered_map mMap; 16 | unordered_map ::iterator it; 17 | 18 | mutex m_mutex; 19 | bool isInit = false; 20 | 21 | /* init gst_init */ 22 | extern "C" void 23 | init(){ 24 | if (!isInit){ 25 | isInit = true; 26 | gst_init (NULL, NULL); 27 | } 28 | 29 | } 30 | 31 | /* create Rtsp client */ 32 | extern "C" int 33 | createRtspClient(int id, const char* url, int conn_mode) 34 | { 35 | m_mutex.lock(); 36 | sleep(2); 37 | init(); 38 | g_print("setup createRtspClient %d %s\n",id,url); 39 | if ( mMap.find(id) != mMap.end() ) { 40 | return SUCCESS; 41 | } 42 | mMap.insert(pair(id ,new RtspClient())); 43 | if (mMap.find(id)->second->enable(id, url, conn_mode)){ 44 | m_mutex.unlock(); 45 | return SUCCESS; 46 | }else{ 47 | m_mutex.unlock(); 48 | return FAIL; 49 | } 50 | } 51 | 52 | extern "C" int 53 | destoryRtspClientAll() 54 | { 55 | m_mutex.lock(); 56 | for( it=mMap.begin(); it!=mMap.end(); it++){ 57 | // cout<first<<" "<second<second != NULL){ 59 | it->second->disable(); 60 | delete it->second; 61 | it->second = NULL; 62 | } 63 | } 64 | mMap.clear(); 65 | malloc_trim(0); 66 | m_mutex.unlock(); 67 | return SUCCESS; 68 | } 69 | 70 | extern "C" int 71 | destoryRtspClient(int id) 72 | { 73 | m_mutex.lock(); 74 | if (mMap.find(id) != mMap.end()){ 75 | if (mMap.find(id)->second != NULL){ 76 | mMap.find(id)->second->disable(); 77 | delete mMap.find(id)->second; 78 | mMap.find(id)->second = NULL; 79 | } 80 | // mMap.erase(id); 81 | malloc_trim(0); 82 | } 83 | m_mutex.unlock(); 84 | return SUCCESS; 85 | } 86 | 87 | extern "C" int 88 | isConnect(int id) 89 | { 90 | if (mMap.find(id) != mMap.end()){ 91 | return mMap.find(id)->second->isConnect(); 92 | }else{ 93 | return STATUS_DISCONNECT; 94 | } 95 | } 96 | 97 | /* change url */ 98 | extern "C" int 99 | changeURL(int id, const char* url, int conn_mode) 100 | { 101 | if (mMap.find(id) != mMap.end()){ 102 | bool ret = mMap.find(id)->second->changeURL(id, url, conn_mode); 103 | if(ret){ 104 | return SUCCESS; 105 | }else{ 106 | return FAIL; 107 | } 108 | }else{ 109 | return FAIL; 110 | } 111 | } 112 | 113 | /* change url */ 114 | extern "C" int 115 | reConnect(int id) 116 | { 117 | if (mMap.find(id) != mMap.end()){ 118 | bool ret = mMap.find(id)->second->reConnect(id); 119 | if(ret){ 120 | return SUCCESS; 121 | }else{ 122 | return FAIL; 123 | } 124 | }else{ 125 | return FAIL; 126 | } 127 | } 128 | 129 | extern "C" int 130 | mRead_Rga(int id, int width, int height, int resize_width, int resize_height, unsigned char * buf, int len, unsigned char * buf_resize, int len_resize) 131 | { 132 | // m_mutex.lock(); 133 | if (mMap.find(id) != mMap.end()){ 134 | if (mMap.find(id)->second != NULL){ 135 | if (mMap.find(id)->second->isConnect() == STATUS_CONNECTED) 136 | { 137 | FrameData *framedata = mMap.find(id)->second->read_Rga(width, height, resize_width, resize_height); 138 | if (framedata->size != 0) { 139 | memcpy( buf, framedata->data, framedata->size); 140 | if (resize_width > 0 and resize_height >0){ 141 | memcpy( buf_resize, framedata->data_resize, framedata->size_resize); 142 | } 143 | free( framedata); 144 | // m_mutex.unlock(); 145 | return SUCCESS; 146 | } 147 | free( framedata); 148 | } 149 | } 150 | } 151 | // m_mutex.unlock(); 152 | return FAIL; 153 | 154 | } 155 | 156 | extern "C" int 157 | mRead_Opencv(int id, int& width, int& height, int& size, char*& data) 158 | { 159 | if (mMap.find(id) != mMap.end()){ 160 | if (mMap.find(id)->second->isConnect() == STATUS_CONNECTED) 161 | { 162 | FrameData *framedata = mMap.find(id)->second->read_Opencv(); 163 | if (framedata->size != 0) { 164 | data = framedata->data; 165 | width = framedata->width; 166 | height = framedata->height; 167 | size = framedata->size; 168 | free( framedata); 169 | return SUCCESS; 170 | } 171 | free( framedata); 172 | } 173 | } 174 | return FAIL; 175 | 176 | } 177 | 178 | //* opencv 179 | extern "C" int 180 | mRead_Python(int id, int& width, int& height,int& size, char* data) 181 | { 182 | if (mMap.find(id) != mMap.end()){ 183 | if (mMap.find(id)->second->isConnect() == STATUS_CONNECTED) 184 | { 185 | FrameData *framedata = mMap.find(id)->second->read_Opencv(); 186 | if (framedata->size != 0) { 187 | // data = framedata->data; 188 | memcpy( data, framedata->data, framedata->size); 189 | width = framedata->width; 190 | height = framedata->height; 191 | size = framedata->size; 192 | free( framedata); 193 | return SUCCESS; 194 | } 195 | free( framedata); 196 | } 197 | } 198 | return FAIL; 199 | 200 | } 201 | -------------------------------------------------------------------------------- /multip_thread_rtsp_rknn.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3.6 2 | import os 3 | import time 4 | import threading 5 | import cv2 6 | import numpy as np 7 | 8 | from multiprocessing import Lock, Process, Condition, Queue 9 | 10 | import gst_rtsp_client_api as rtspclient 11 | 12 | from rknnlite.api import RKNNLite 13 | 14 | # from ctypes import * 15 | 16 | GRID0 = 13 17 | GRID1 = 26 18 | GRID2 = 52 19 | LISTSIZE = 8 20 | SPAN = 3 21 | NUM_CLS = 3 22 | MAX_BOXES = 500 23 | OBJ_THRESH = 0.9 24 | NMS_THRESH = 0.2 25 | 26 | CLASSES = ("phone","call_phone","play_phone") 27 | 28 | def sigmoid(x): 29 | return 1 / (1 + np.exp(-x)) 30 | 31 | 32 | def process(input, mask, anchors): 33 | 34 | anchors = [anchors[i] for i in mask] 35 | grid_h, grid_w = map(int, input.shape[0:2]) 36 | 37 | box_confidence = sigmoid(input[..., 4]) 38 | box_confidence = np.expand_dims(box_confidence, axis=-1) 39 | 40 | box_class_probs = sigmoid(input[..., 5:]) 41 | 42 | box_xy = sigmoid(input[..., :2]) 43 | box_wh = np.exp(input[..., 2:4]) 44 | box_wh = box_wh * anchors 45 | 46 | col = np.tile(np.arange(0, grid_w), grid_w).reshape(-1, grid_w) 47 | row = np.tile(np.arange(0, grid_h).reshape(-1, 1), grid_h) 48 | 49 | col = col.reshape(grid_h, grid_w, 1, 1).repeat(3, axis=-2) 50 | row = row.reshape(grid_h, grid_w, 1, 1).repeat(3, axis=-2) 51 | grid = np.concatenate((col, row), axis=-1) 52 | 53 | box_xy += grid 54 | box_xy /= (grid_w, grid_h) 55 | box_wh /= (416, 416) 56 | box_xy -= (box_wh / 2.) 57 | box = np.concatenate((box_xy, box_wh), axis=-1) 58 | 59 | return box, box_confidence, box_class_probs 60 | 61 | def filter_boxes(boxes, box_confidences, box_class_probs): 62 | """Filter boxes with object threshold. 63 | 64 | # Arguments 65 | boxes: ndarray, boxes of objects. 66 | box_confidences: ndarray, confidences of objects. 67 | box_class_probs: ndarray, class_probs of objects. 68 | 69 | # Returns 70 | boxes: ndarray, filtered boxes. 71 | classes: ndarray, classes for boxes. 72 | scores: ndarray, scores for boxes. 73 | """ 74 | box_scores = box_confidences * box_class_probs 75 | box_classes = np.argmax(box_scores, axis=-1) 76 | box_class_scores = np.max(box_scores, axis=-1) 77 | pos = np.where(box_class_scores >= OBJ_THRESH) 78 | 79 | boxes = boxes[pos] 80 | classes = box_classes[pos] 81 | scores = box_class_scores[pos] 82 | 83 | return boxes, classes, scores 84 | 85 | def nms_boxes(boxes, scores): 86 | """Suppress non-maximal boxes. 87 | 88 | # Arguments 89 | boxes: ndarray, boxes of objects. 90 | scores: ndarray, scores of objects. 91 | 92 | # Returns 93 | keep: ndarray, index of effective boxes. 94 | """ 95 | x = boxes[:, 0] 96 | y = boxes[:, 1] 97 | w = boxes[:, 2] 98 | h = boxes[:, 3] 99 | 100 | areas = w * h 101 | order = scores.argsort()[::-1] 102 | keep = [] 103 | while order.size > 0: 104 | i = order[0] 105 | keep.append(i) 106 | 107 | xx1 = np.maximum(x[i], x[order[1:]]) 108 | yy1 = np.maximum(y[i], y[order[1:]]) 109 | xx2 = np.minimum(x[i] + w[i], x[order[1:]] + w[order[1:]]) 110 | yy2 = np.minimum(y[i] + h[i], y[order[1:]] + h[order[1:]]) 111 | 112 | w1 = np.maximum(0.0, xx2 - xx1 + 0.00001) 113 | h1 = np.maximum(0.0, yy2 - yy1 + 0.00001) 114 | inter = w1 * h1 115 | 116 | ovr = inter / (areas[i] + areas[order[1:]] - inter) 117 | inds = np.where(ovr <= NMS_THRESH)[0] 118 | order = order[inds + 1] 119 | keep = np.array(keep) 120 | return keep 121 | 122 | 123 | def yolov3_post_process(input_data): 124 | # yolov3 125 | masks = [[6, 7, 8], [3, 4, 5], [0, 1, 2]] 126 | anchors = [[10, 13], [16, 30], [33, 23], [30, 61], [62, 45], 127 | [59, 119], [116, 90], [156, 198], [373, 326]] 128 | # yolov3-tiny 129 | # masks = [[3, 4, 5], [0, 1, 2]] 130 | # anchors = [[10, 14], [23, 27], [37, 58], [81, 82], [135, 169], [344, 319]] 131 | 132 | boxes, classes, scores = [], [], [] 133 | for input,mask in zip(input_data, masks): 134 | b, c, s = process(input, mask, anchors) 135 | b, c, s = filter_boxes(b, c, s) 136 | boxes.append(b) 137 | classes.append(c) 138 | scores.append(s) 139 | 140 | boxes = np.concatenate(boxes) 141 | classes = np.concatenate(classes) 142 | scores = np.concatenate(scores) 143 | 144 | nboxes, nclasses, nscores = [], [], [] 145 | for c in set(classes): 146 | inds = np.where(classes == c) 147 | b = boxes[inds] 148 | c = classes[inds] 149 | s = scores[inds] 150 | 151 | keep = nms_boxes(b, s) 152 | 153 | nboxes.append(b[keep]) 154 | nclasses.append(c[keep]) 155 | nscores.append(s[keep]) 156 | 157 | if not nclasses and not nscores: 158 | return None, None, None 159 | 160 | boxes = np.concatenate(nboxes) 161 | classes = np.concatenate(nclasses) 162 | scores = np.concatenate(nscores) 163 | 164 | return boxes, classes, scores 165 | 166 | def draw(image, boxes, scores, classes): 167 | """Draw the boxes on the image. 168 | 169 | # Argument: 170 | image: original image. 171 | boxes: ndarray, boxes of objects. 172 | classes: ndarray, classes of objects. 173 | scores: ndarray, scores of objects. 174 | all_classes: all classes name. 175 | """ 176 | for box, score, cl in zip(boxes, scores, classes): 177 | x, y, w, h = box 178 | print('class: {}, score: {}'.format(CLASSES[cl], score)) 179 | print('box coordinate left,top,right,down: [{}, {}, {}, {}]'.format(x, y, x+w, y+h)) 180 | 181 | x *= image.shape[1] 182 | y *= image.shape[0] 183 | w *= image.shape[1] 184 | h *= image.shape[0] 185 | print("image.shape[]"+str(image.shape[0])) 186 | print("image.shape[]"+str(image.shape[1])) 187 | top = max(0, np.floor(x + 0.5).astype(int)) 188 | left = max(0, np.floor(y + 0.5).astype(int)) 189 | right = min(image.shape[1], np.floor(x + w + 0.5).astype(int)) 190 | bottom = min(image.shape[0], np.floor(y + h + 0.5).astype(int)) 191 | 192 | cv2.rectangle(image, (top, left), (right, bottom), (255, 0, 0), 2) 193 | cv2.putText(image, '{0} {1:.2f}'.format(CLASSES[cl], score), 194 | (top, left - 6), 195 | cv2.FONT_HERSHEY_SIMPLEX, 196 | 0.6, (0, 0, 255), 2) 197 | 198 | def download_yolov3_weight(dst_path): 199 | if os.path.exists(dst_path): 200 | print('yolov3.weight exist.') 201 | return 202 | print('Downloading yolov3.weights...') 203 | url = 'https://pjreddie.com/media/files/yolov3.weights' 204 | try: 205 | urllib.request.urlretrieve(url, dst_path) 206 | except urllib.error.HTTPError as e: 207 | print('HTTPError code: ', e.code) 208 | print('HTTPError reason: ', e.reason) 209 | exit(-1) 210 | except urllib.error.URLError as e: 211 | print('URLError reason: ', e.reason) 212 | else: 213 | print('Download yolov3.weight success.') 214 | 215 | def func_rtspdisplay(index,url, usr, pwd): 216 | 217 | width = 1920 218 | height = 1080 219 | 220 | # c_url = create_string_buffer(url.encode('utf-8'), len(url)) 221 | # ret = rtspclient.createRtspClient(index,url) 222 | 223 | RKNN_MODEL_PATH = '/home/toybrick/Dev/gst_rtsp_client/yolov3_phone_q_p.rknn' 224 | 225 | rknn = RKNNLite() 226 | print('Loading RKNN model') 227 | ret = rknn.load_rknn(RKNN_MODEL_PATH) 228 | if ret != 0: 229 | print('load rknn model failed.') 230 | exit(ret) 231 | print('done') 232 | 233 | print('--> init runtime') 234 | ret = rknn.init_runtime() 235 | if ret != 0: 236 | # i 237 | print('init runtime failed.') 238 | exit(ret) 239 | print('done') 240 | 241 | last = time.time() 242 | 243 | while(1) : 244 | ret1 = rtspclient.isConnect(index) 245 | time.sleep(0.5) 246 | print("id %d ret = %d",index, ret1) 247 | if (ret1 == 1): 248 | now = time.time() 249 | ret2 = rtspclient.mread(index,width,height) 250 | print(ret2.status) 251 | # print(type(img)) 252 | # img = cv2.resize(img,(1920,1080,3)) 253 | # img = cv2.UMat(height,width,cv2.CV_8UC3,img) 254 | # inference 255 | print('--> inference') 256 | # #img = cv2.resize(frame,(416,416)) 257 | 258 | img = ret2.frame 259 | img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) 260 | img = cv2.resize(img,(416,416)) 261 | outputs = rknn.inference(inputs=[img]) 262 | print('done') 263 | 264 | #print(len(outputs)) 265 | #print(outputs[0].shape) 266 | 267 | input0_data = outputs[0] 268 | input1_data = outputs[1] 269 | input2_data = outputs[2] 270 | 271 | input0_data = input0_data.reshape(SPAN, LISTSIZE, GRID0, GRID0) 272 | input1_data = input1_data.reshape(SPAN, LISTSIZE, GRID1, GRID1) 273 | input2_data = input2_data.reshape(SPAN, LISTSIZE, GRID2, GRID2) 274 | 275 | input_data = [] 276 | input_data.append(np.transpose(input0_data, (2, 3, 0, 1))) 277 | input_data.append(np.transpose(input1_data, (2, 3, 0, 1))) 278 | input_data.append(np.transpose(input2_data, (2, 3, 0, 1))) 279 | 280 | boxes, classes, scores = yolov3_post_process(input_data) 281 | 282 | if boxes is not None: 283 | print("phone") 284 | # draw(frame.array(), boxes, scores, classes) 285 | 286 | # gl.show(idx0, frame) 287 | # print (frame_index, "----------------------------",now - last) 288 | # frame = frame.array() 289 | #cv2.imwrite("images/4_" + str(frame_index) + ".jpg", frame) 290 | #cv2.imshow('Carplate demo', cv2.resize(frame, (960, 540))) # 291 | # cv2.waitKey(1) 292 | # frame_index += 1 293 | last = now 294 | 295 | cv2.imwrite('a' + str(index) +'.jpg',ret2.frame) 296 | elif (ret1 == 2): 297 | #time.sleep(4) 298 | rtspclient.createRtspClient(index,url) 299 | #time.sleep(10) 300 | 301 | print('# End of Thread %d' % (index)) 302 | 303 | 304 | if __name__ == '__main__': 305 | os.system('iptables -F') # Disable Firewall 306 | 307 | #gl = toy.output.createGLDrmDisplay(toy.DisplayPort.HDMI_A) 308 | #idx0 = gl.add_view(0, 180, 640, 360) 309 | # idx1 = gl.add_view(640, 180, 640, 360) 310 | # idx2 = gl.add_view(1280, 180, 640, 360) 311 | # idx3 = gl.add_view(0, 540, 640, 360) 312 | # idx4 = gl.add_view(640, 540, 640, 360) 313 | # idx5 = gl.add_view(1280, 540, 640, 360) 314 | 315 | t5 = threading.Thread(target=func_rtspdisplay, args = (6, "rtsp://admin:passwd@192.168.2.35/Streaming/Channels/1", "admin", "passwd")) 316 | 317 | t5.start() 318 | 319 | t5.join() 320 | -------------------------------------------------------------------------------- /test/c_test_main_rtsp.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | // rtsp lib 7 | #include <../include/gst_rtsp_client.h> 8 | #include <../src/setup.cpp> 9 | 10 | // opencv2 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace std; 17 | 18 | // sleep for ms 19 | static void sleep_ms(unsigned int secs) 20 | { 21 | struct timeval tval; 22 | tval.tv_sec=secs/1000; 23 | tval.tv_usec=(secs*1000)%1000000; 24 | select(0,NULL,NULL,NULL,&tval); 25 | } 26 | 27 | 28 | int main() 29 | { 30 | 31 | // multi rtsp 32 | const char* urlerror = "rtsp://admin:shangqu20201@192.168.2.29:554/cam/realmonitor?channel=1&subtype=0"; 33 | 34 | const char* url1 = "rtsp://admin:shangqu2020@192.168.2.29:554/cam/realmonitor?channel=1&subtype=0"; 35 | const char* url2 = "rtsp://admin:shangqu2020@192.168.2.24:554/cam/realmonitor?channel=1&subtype=0"; 36 | const char* url3 = "rtsp://admin:shangqu2020@192.168.2.8:554/Streaming/Channels/101"; 37 | const char* url4 = "rtsp://admin:shangqu2020@192.168.2.27:554/cam/realmonitor?channel=1&subtype=0"; 38 | const char* url5 = "rtsp://admin:shangqu2020@192.168.2.29:554/cam/realmonitor?channel=1&subtype=0"; 39 | const char* url6 = "rtsp://admin:shangqu2020@192.168.2.8:554/Streaming/Channels/201"; 40 | const char* url7 = "rtsp://admin:shangqu2020@192.168.2.33:554/Streaming/Channels/1"; 41 | const char* url8 = "rtsp://admin:shangqu2020@192.168.2.39:554/Streaming/Channels/1"; 42 | 43 | init(); 44 | 45 | createRtspClient(0, urlerror, TCP_CONN_MODE); 46 | createRtspClient(1, url2, TCP_CONN_MODE); 47 | createRtspClient(2, url3, TCP_CONN_MODE); 48 | createRtspClient(3, url4, TCP_CONN_MODE); 49 | createRtspClient(4, url5, TCP_CONN_MODE); 50 | createRtspClient(5, url6, TCP_CONN_MODE); 51 | createRtspClient(6, url7, TCP_CONN_MODE); 52 | createRtspClient(7, url8, TCP_CONN_MODE); 53 | int i = 0; 54 | int status = 0; 55 | 56 | do { 57 | 58 | if (isConnect(0) == STATUS_CONNECTED) 59 | { 60 | //rga 61 | // unsigned char* buf = (unsigned char *)malloc(1920*1080*3); 62 | // unsigned char* buf_resize = (unsigned char *)malloc(640*640*3); 63 | // status = mRead_Rga(0,1920,1080,640,640,buf , 1920*1080*3, buf_resize, 640*640*3); 64 | // free(buf); 65 | // free(buf_resize); 66 | g_print("id:0 connected\n"); 67 | 68 | //opencv 69 | int width; 70 | int height; 71 | int size; 72 | char* data; 73 | status = mRead_Opencv(0,width,height,size,data); 74 | if (status == 1){ 75 | cv::Mat yuvNV12(height * 3 / 2,width, CV_8UC1, data); 76 | cv::Mat rgb24(height, width , CV_8UC3); 77 | cv::cvtColor(yuvNV12, rgb24, cv::COLOR_YUV2BGR_NV12); 78 | cv::Mat croprgb(1080,1920,CV_8UC3); 79 | croprgb = rgb24(cv::Rect(0,0,1920,1080)); // 裁剪后的图 80 | } 81 | 82 | } else { 83 | g_print("id:0 disconnect %d \n", isConnect(0)); 84 | sleep_ms(500); 85 | if (i == 0){ 86 | g_print("changeURL******************** %d \n", isConnect(0)); 87 | i = i+1; 88 | sleep_ms(500); 89 | changeURL(0,url1,TCP_CONN_MODE); 90 | } else 91 | if (isConnect(0) == STATUS_DISCONNECT) { 92 | g_print("reConnect******************** %d \n", isConnect(0)); 93 | sleep_ms(500); 94 | reConnect(0); 95 | } 96 | } 97 | 98 | if (isConnect(1) == STATUS_CONNECTED) 99 | { 100 | //rga 101 | // unsigned char* buf = (unsigned char *)malloc(1920*1080*3); 102 | // unsigned char* buf_resize = (unsigned char *)malloc(640*640*3); 103 | // status = mRead_Rga(1,1920,1080,640,640,buf , 1920*1080*3, buf_resize, 640*640*3); 104 | // free(buf); 105 | // free(buf_resize); 106 | g_print("id:1 connected\n"); 107 | 108 | //opencv 109 | int width; 110 | int height; 111 | int size; 112 | char* data; 113 | status = mRead_Opencv(1,width,height,size,data); 114 | if (status == 1){ 115 | cv::Mat yuvNV12(height * 3 / 2,width, CV_8UC1, data); 116 | cv::Mat rgb24(height, width , CV_8UC3); 117 | cv::cvtColor(yuvNV12, rgb24, cv::COLOR_YUV2BGR_NV12); 118 | cv::Mat croprgb(1080,1920,CV_8UC3); 119 | croprgb = rgb24(cv::Rect(0,0,1920,1080)); // 裁剪后的图 120 | } 121 | 122 | } else { 123 | g_print("id:1 disconnect %d \n", isConnect(1)); 124 | sleep_ms(500); 125 | if (isConnect(1) == STATUS_DISCONNECT) { 126 | sleep_ms(500); 127 | reConnect(1); 128 | } 129 | } 130 | 131 | if (isConnect(2) == STATUS_CONNECTED) 132 | { 133 | //rga 134 | // unsigned char* buf = (unsigned char *)malloc(1920*1080*3); 135 | // unsigned char* buf_resize = (unsigned char *)malloc(640*640*3); 136 | // status = mRead_Rga(2,1920,1080,640,640,buf , 1920*1080*3, buf_resize, 640*640*3); 137 | // free(buf); 138 | // free(buf_resize); 139 | g_print("id:2 connected\n"); 140 | 141 | //opencv 142 | int width; 143 | int height; 144 | int size; 145 | char* data; 146 | status = mRead_Opencv(2,width,height,size,data); 147 | if (status == 1){ 148 | cv::Mat yuvNV12(height * 3 / 2,width, CV_8UC1, data); 149 | cv::Mat rgb24(height, width , CV_8UC3); 150 | cv::cvtColor(yuvNV12, rgb24, cv::COLOR_YUV2BGR_NV12); 151 | cv::Mat croprgb(1080,1920,CV_8UC3); 152 | croprgb = rgb24(cv::Rect(0,0,1920,1080)); // 裁剪后的图 153 | } 154 | 155 | } else { 156 | g_print("id:2 disconnect %d \n", isConnect(2)); 157 | sleep_ms(500); 158 | if (isConnect(2) == STATUS_DISCONNECT) { 159 | sleep_ms(500); 160 | reConnect(2); 161 | } 162 | } 163 | 164 | if (isConnect(3) == STATUS_CONNECTED) 165 | { 166 | //rga 167 | // unsigned char* buf = (unsigned char *)malloc(1920*1080*3); 168 | // unsigned char* buf_resize = (unsigned char *)malloc(640*640*3); 169 | // status = mRead_Rga(3,1920,1080,640,640,buf , 1920*1080*3, buf_resize, 640*640*3); 170 | // free(buf); 171 | // free(buf_resize); 172 | g_print("id:3 connected\n"); 173 | 174 | //opencv 175 | int width; 176 | int height; 177 | int size; 178 | char* data; 179 | status = mRead_Opencv(3,width,height,size,data); 180 | if (status == 1){ 181 | cv::Mat yuvNV12(height * 3 / 2,width, CV_8UC1, data); 182 | cv::Mat rgb24(height, width , CV_8UC3); 183 | cv::cvtColor(yuvNV12, rgb24, cv::COLOR_YUV2BGR_NV12); 184 | cv::Mat croprgb(1080,1920,CV_8UC3); 185 | croprgb = rgb24(cv::Rect(0,0,1920,1080)); // 裁剪后的图 186 | } 187 | 188 | } else { 189 | g_print("id:3 disconnect %d \n", isConnect(3)); 190 | sleep_ms(500); 191 | if (isConnect(3) == STATUS_DISCONNECT) { 192 | sleep_ms(500); 193 | reConnect(3); 194 | } 195 | } 196 | 197 | if (isConnect(4) == STATUS_CONNECTED) 198 | { 199 | //rga 200 | // unsigned char* buf = (unsigned char *)malloc(1920*1080*3); 201 | // unsigned char* buf_resize = (unsigned char *)malloc(640*640*3); 202 | // status = mRead_Rga(4,1920,1080,640,640,buf , 1920*1080*3, buf_resize, 640*640*3); 203 | // free(buf); 204 | // free(buf_resize); 205 | g_print("id:4 connected\n"); 206 | 207 | //opencv 208 | int width; 209 | int height; 210 | int size; 211 | char* data; 212 | status = mRead_Opencv(4,width,height,size,data); 213 | if (status == 1){ 214 | cv::Mat yuvNV12(height * 3 / 2,width, CV_8UC1, data); 215 | cv::Mat rgb24(height, width , CV_8UC3); 216 | cv::cvtColor(yuvNV12, rgb24, cv::COLOR_YUV2BGR_NV12); 217 | cv::Mat croprgb(1080,1920,CV_8UC3); 218 | croprgb = rgb24(cv::Rect(0,0,1920,1080)); // 裁剪后的图 219 | } 220 | 221 | } else { 222 | g_print("id:4 disconnect %d \n", isConnect(4)); 223 | sleep_ms(500); 224 | if (isConnect(4) == STATUS_DISCONNECT) { 225 | sleep_ms(500); 226 | reConnect(4); 227 | } 228 | } 229 | 230 | if (isConnect(5) == STATUS_CONNECTED) 231 | { 232 | //rga 233 | // unsigned char* buf = (unsigned char *)malloc(1920*1080*3); 234 | // unsigned char* buf_resize = (unsigned char *)malloc(640*640*3); 235 | // status = mRead_Rga(5,1920,1080,640,640,buf , 1920*1080*3, buf_resize, 640*640*3); 236 | // free(buf); 237 | // free(buf_resize); 238 | g_print("id:5 connected\n"); 239 | 240 | //opencv 241 | int width; 242 | int height; 243 | int size; 244 | char* data; 245 | status = mRead_Opencv(5,width,height,size,data); 246 | if (status == 1){ 247 | cv::Mat yuvNV12(height * 3 / 2,width, CV_8UC1, data); 248 | cv::Mat rgb24(height, width , CV_8UC3); 249 | cv::cvtColor(yuvNV12, rgb24, cv::COLOR_YUV2BGR_NV12); 250 | cv::Mat croprgb(1080,1920,CV_8UC3); 251 | croprgb = rgb24(cv::Rect(0,0,1920,1080)); // 裁剪后的图 252 | } 253 | 254 | } else { 255 | g_print("id:5 disconnect %d \n", isConnect(5)); 256 | sleep_ms(500); 257 | if (isConnect(5) == STATUS_DISCONNECT) { 258 | sleep_ms(500); 259 | reConnect(5); 260 | } 261 | } 262 | 263 | if (isConnect(6) == STATUS_CONNECTED) 264 | { 265 | //rga 266 | // unsigned char* buf = (unsigned char *)malloc(1920*1080*3); 267 | // unsigned char* buf_resize = (unsigned char *)malloc(640*640*3); 268 | // status = mRead_Rga(6,1920,1080,640,640,buf , 1920*1080*3, buf_resize, 640*640*3); 269 | // free(buf); 270 | // free(buf_resize); 271 | g_print("id:6 connected\n"); 272 | 273 | //opencv 274 | int width; 275 | int height; 276 | int size; 277 | char* data; 278 | status = mRead_Opencv(6,width,height,size,data); 279 | if (status == 1){ 280 | cv::Mat yuvNV12(height * 3 / 2,width, CV_8UC1, data); 281 | cv::Mat rgb24(height, width , CV_8UC3); 282 | cv::cvtColor(yuvNV12, rgb24, cv::COLOR_YUV2BGR_NV12); 283 | cv::Mat croprgb(1080,1920,CV_8UC3); 284 | croprgb = rgb24(cv::Rect(0,0,1920,1080)); // 裁剪后的图 285 | } 286 | 287 | } else { 288 | g_print("id:6 disconnect %d \n", isConnect(6)); 289 | sleep_ms(500); 290 | if (isConnect(6) == STATUS_DISCONNECT) { 291 | sleep_ms(500); 292 | reConnect(6); 293 | } 294 | } 295 | 296 | if (isConnect(7) == STATUS_CONNECTED) 297 | { 298 | //rga 299 | // unsigned char* buf = (unsigned char *)malloc(1920*1080*3); 300 | // unsigned char* buf_resize = (unsigned char *)malloc(640*640*3); 301 | // status = mRead_Rga(7,1920,1080,640,640,buf , 1920*1080*3, buf_resize, 640*640*3); 302 | // free(buf); 303 | // free(buf_resize); 304 | g_print("id:7 connected\n"); 305 | 306 | //opencv 307 | int width; 308 | int height; 309 | int size; 310 | char* data; 311 | status = mRead_Opencv(7,width,height,size,data); 312 | if (status == 1){ 313 | cv::Mat yuvNV12(height * 3 / 2,width, CV_8UC1, data); 314 | cv::Mat rgb24(height, width , CV_8UC3); 315 | cv::cvtColor(yuvNV12, rgb24, cv::COLOR_YUV2BGR_NV12); 316 | cv::Mat croprgb(1080,1920,CV_8UC3); 317 | croprgb = rgb24(cv::Rect(0,0,1920,1080)); // 裁剪后的图 318 | } 319 | 320 | } else { 321 | g_print("id:7 disconnect %d \n", isConnect(7)); 322 | sleep_ms(500); 323 | if (isConnect(7) == STATUS_DISCONNECT) { 324 | sleep_ms(500); 325 | reConnect(7); 326 | } 327 | } 328 | 329 | 330 | } while (1); 331 | 332 | // // cv::Mat img(480, 640 , CV_8UC3, framedata.data); 333 | // // char buf1[32] = {0}; 334 | // // snprintf(buf1, sizeof(buf1), "%u",sizeof(time(NULL))); 335 | // // std::string str = buf1; 336 | // // std::string name = str + "test.jpg"; 337 | 338 | // // cv::imwrite( name, img); 339 | 340 | cout << "hellow\n"; 341 | return 0; 342 | } 343 | -------------------------------------------------------------------------------- /src/gst_rtsp_client.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | // gst 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | // rga 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | // opencv2 43 | #include 44 | #include 45 | #include 46 | #include 47 | 48 | // static GstFlowReturn 49 | // new_sample (GstElement *sink, GMainLoop *pipline) { 50 | // GstSample *sample; 51 | 52 | // g_signal_emit_by_name(sink,"pull-sample", &sample); 53 | // if (sample) { 54 | // g_print ("*"); 55 | // gst_sample_unref (sample); 56 | // return GST_FLOW_OK; 57 | // } 58 | 59 | // return GST_FLOW_ERROR; 60 | // } 61 | 62 | // appsink probe 63 | static GstPadProbeReturn 64 | pad_probe (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) 65 | { 66 | struct CustomData *dec = (struct CustomData *) user_data; 67 | GstEvent *event = GST_PAD_PROBE_INFO_EVENT (info); 68 | GstCaps *caps; 69 | 70 | (void) pad; 71 | 72 | if (GST_EVENT_TYPE (event) != GST_EVENT_CAPS) 73 | return GST_PAD_PROBE_OK; 74 | 75 | gst_event_parse_caps (event, &caps); 76 | 77 | if (!caps) { 78 | GST_ERROR ("caps event without caps"); 79 | return GST_PAD_PROBE_OK; 80 | } 81 | 82 | if (!gst_video_info_from_caps (&dec->info, caps)) { 83 | GST_ERROR ("caps event with invalid video caps"); 84 | return GST_PAD_PROBE_OK; 85 | } 86 | 87 | switch (GST_VIDEO_INFO_FORMAT (&(dec->info))) { 88 | case GST_VIDEO_FORMAT_I420: 89 | dec->format = 2; 90 | break; 91 | case GST_VIDEO_FORMAT_NV12: 92 | dec->format = 23; 93 | break; 94 | case GST_VIDEO_FORMAT_YUY2: 95 | dec->format = 4; 96 | break; 97 | default: 98 | GST_ERROR ("unknown format\n"); 99 | return GST_PAD_PROBE_OK; 100 | } 101 | 102 | dec->isRun = STATUS_CONNECTED; 103 | 104 | return GST_PAD_PROBE_OK; 105 | } 106 | 107 | // uridecodebin -> src link tee -> sink 108 | static void 109 | on_src_tee_added(GstElement *element, GstPad *pad, gpointer data) { 110 | // GstPad *sinkpad; 111 | struct CustomData *decoder = (struct CustomData *)data; 112 | 113 | /* We can now link this pad with the rtsp-decoder sink pad */ 114 | g_print("Dynamic pad created, linking source/demuxer\n"); 115 | GstPad * tee_sinkpad = gst_element_get_static_pad(decoder->tee, "sink"); 116 | gst_pad_link(pad, tee_sinkpad); 117 | gst_object_unref(tee_sinkpad); 118 | } 119 | 120 | static void 121 | on_src_decodebin_added(GstElement *element, GstPad *pad, gpointer data) { 122 | struct CustomData *decoder = (struct CustomData *)data; 123 | 124 | // decoder->isRun = STATUS_CONNECTED; 125 | /* We can now link this pad with the rtsp-decoder sink pad */ 126 | g_print("Dynamic pad created, linking source/decodeon_src_decodebin_added\n"); 127 | GstPad * decode_sinkpad = gst_element_get_static_pad(decoder->decode, "sink"); 128 | gst_pad_link(pad, decode_sinkpad); 129 | gst_object_unref(decode_sinkpad); 130 | } 131 | 132 | // appsink query 133 | static GstPadProbeReturn 134 | appsink_query_cb (GstPad * pad G_GNUC_UNUSED, GstPadProbeInfo * info, 135 | gpointer user_data G_GNUC_UNUSED) 136 | { 137 | GstQuery *query = (GstQuery *) info->data; 138 | 139 | if (GST_QUERY_TYPE (query) != GST_QUERY_ALLOCATION) 140 | return GST_PAD_PROBE_OK; 141 | 142 | gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL); 143 | 144 | return GST_PAD_PROBE_HANDLED; 145 | } 146 | 147 | // bus 148 | static gboolean 149 | bus_watch_cb (GstBus * bus, GstMessage * msg, gpointer user_data) 150 | { 151 | struct CustomData *dec = (struct CustomData *) user_data; 152 | 153 | //param not use 154 | // (void) bus; 155 | // g_print ( "piple call_bus message m_Id %s %d \n", gst_message_type_get_name(GST_MESSAGE_TYPE (msg)),dec->m_Id); 156 | 157 | 158 | switch (GST_MESSAGE_TYPE (msg)) { 159 | case GST_MESSAGE_UNKNOWN: { 160 | g_print ( "piple call_bus message GST_MESSAGE_UNKNOWN %d \n",dec->m_Id); 161 | } 162 | case GST_MESSAGE_STATE_CHANGED:{ 163 | gchar *dotfilename; 164 | GstState old_gst_state, cur_gst_state, pending_gst_state; 165 | 166 | /* Only consider state change messages coming from 167 | * the toplevel element. */ 168 | if (GST_MESSAGE_SRC (msg) != GST_OBJECT (dec->pipeline)) 169 | break; 170 | 171 | gst_message_parse_state_changed (msg, &old_gst_state, &cur_gst_state, 172 | &pending_gst_state); 173 | 174 | printf ("GStreamer state change: old: %s current: %s pending: %s\n", 175 | gst_element_state_get_name (old_gst_state), 176 | gst_element_state_get_name (cur_gst_state), 177 | gst_element_state_get_name (pending_gst_state) 178 | ); 179 | 180 | dotfilename = g_strdup_printf ("statechange__old-%s__cur-%s__pending-%s", 181 | gst_element_state_get_name (old_gst_state), 182 | gst_element_state_get_name (cur_gst_state), 183 | gst_element_state_get_name (pending_gst_state) 184 | ); 185 | GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (dec->pipeline), 186 | GST_DEBUG_GRAPH_SHOW_ALL, dotfilename); 187 | 188 | // g_print ( "piple call_bus message GST_MESSAGE_STATE_CHANGED %d \n",dec->m_Id); 189 | 190 | g_free (dotfilename); 191 | 192 | break; 193 | } 194 | case GST_MESSAGE_REQUEST_STATE:{ 195 | GstState requested_state; 196 | gst_message_parse_request_state (msg, &requested_state); 197 | printf ("state change to %s was requested by %s\n", 198 | gst_element_state_get_name (requested_state), 199 | GST_MESSAGE_SRC_NAME (msg) 200 | ); 201 | gst_element_set_state (GST_ELEMENT (dec->pipeline), requested_state); 202 | break; 203 | } 204 | case GST_MESSAGE_LATENCY:{ 205 | printf ("redistributing latency\n"); 206 | gst_bin_recalculate_latency (GST_BIN (dec->pipeline)); 207 | break; 208 | } 209 | case GST_MESSAGE_EOS: 210 | g_print("bus eos \n"); 211 | // g_main_loop_quit (dec->loop); 212 | // dec->isRun = STATUS_DISCONNECT; 213 | break; 214 | case GST_MESSAGE_INFO: 215 | case GST_MESSAGE_WARNING: 216 | case GST_MESSAGE_ERROR:{ 217 | g_print ( "piple call_bus message %d \n",dec->m_Id); 218 | GError *error = NULL; 219 | gchar *debug_info = NULL; 220 | gchar const *prefix = ""; 221 | 222 | switch (GST_MESSAGE_TYPE (msg)) { 223 | case GST_MESSAGE_INFO: 224 | gst_message_parse_info (msg, &error, &debug_info); 225 | prefix = "INFO"; 226 | break; 227 | case GST_MESSAGE_WARNING: 228 | gst_message_parse_warning (msg, &error, &debug_info); 229 | prefix = "WARNING"; 230 | break; 231 | case GST_MESSAGE_ERROR: 232 | gst_message_parse_error (msg, &error, &debug_info); 233 | prefix = "ERROR"; 234 | break; 235 | default: 236 | g_assert_not_reached (); 237 | } 238 | g_print ("GStreamer %s: %s; debug info: %s \n", prefix, error->message, 239 | debug_info); 240 | 241 | g_clear_error (&error); 242 | g_free (debug_info); 243 | 244 | if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR) { 245 | GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (dec->pipeline), 246 | GST_DEBUG_GRAPH_SHOW_ALL, "error"); 247 | } 248 | // TODO: stop mainloop in case of an error 249 | // g_main_loop_quit(dec->loop); 250 | // g_print("bus disconnect %d \n",dec->m_Id); 251 | // dec->isRun = STATUS_DISCONNECT; 252 | 253 | break; 254 | } 255 | default: 256 | break; 257 | } 258 | 259 | return TRUE; 260 | } 261 | 262 | // static void 263 | // buffer_to_file (struct CustomData *dec, GstBuffer * buf) 264 | // { 265 | // int ret; 266 | // GstVideoMeta *meta = gst_buffer_get_video_meta (buf); 267 | // guint nplanes = GST_VIDEO_INFO_N_PLANES (&(dec->info)); 268 | // guint width, height; 269 | // GstMapInfo map_info; 270 | // gchar filename[128]; 271 | // GstVideoFormat pixfmt; 272 | // const char *pixfmt_str; 273 | 274 | // pixfmt = GST_VIDEO_INFO_FORMAT (&(dec->info)); 275 | // pixfmt_str = gst_video_format_to_string (pixfmt); 276 | 277 | // /* TODO: use the DMABUF directly */ 278 | 279 | // gst_buffer_map (buf, &map_info, GST_MAP_READ); 280 | 281 | // width = GST_VIDEO_INFO_WIDTH (&(dec->info)); 282 | // height = GST_VIDEO_INFO_HEIGHT (&(dec->info)); 283 | 284 | // /* output some information at the beginning (= when the first frame is handled) */ 285 | // if (dec->frame == 0) { 286 | // printf ("===================================\n"); 287 | // printf ("GStreamer video stream information:\n"); 288 | // printf (" size: %u x %u pixel\n", width, height); 289 | // printf (" pixel format: %s number of planes: %u\n", pixfmt_str, nplanes); 290 | // printf (" video meta found: %s\n", yesno (meta != NULL)); 291 | // printf ("===================================\n"); 292 | // } 293 | 294 | // gst_buffer_unmap (buf, &map_info); 295 | 296 | // return; 297 | // } 298 | 299 | // static void * 300 | // video_frame_loop (void *arg) 301 | // { 302 | // struct CustomData *dec = (struct CustomData *) arg; 303 | 304 | // // gst_app_sink_set_max_buffers (GST_APP_SINK(dec->appsink),1); 305 | // // gst_app_sink_set_buffer_list_support (GST_APP_SINK(dec->appsink),FALSE); 306 | 307 | // do { 308 | // GstSample *samp; 309 | // GstBuffer *buf; 310 | 311 | // samp = gst_app_sink_pull_sample (GST_APP_SINK (dec->appsink)); 312 | // // samp = gst_app_sink_try_pull_sample (GST_APP_SINK (dec->appsink),100000); 313 | // if (!samp) { 314 | // GST_DEBUG ("got no appsink sample"); 315 | // if (gst_app_sink_is_eos (GST_APP_SINK (dec->appsink))) 316 | // GST_DEBUG ("eos"); 317 | // return((void *)0); 318 | // } 319 | 320 | // buf = gst_sample_get_buffer (samp); 321 | // buffer_to_file (dec, buf); 322 | 323 | // gst_sample_unref (samp); 324 | // dec->frame++; 325 | 326 | // // sleep(2); 327 | 328 | // } while (1); 329 | 330 | // return((void *)0); 331 | 332 | // } 333 | 334 | // rtsp init 335 | static int 336 | rtsp_init(struct CustomData *data) { 337 | 338 | /* Build Pipeline */ 339 | data->pipeline = gst_pipeline_new(std::to_string(data->m_Id).c_str()); 340 | g_print(("rtsp_init rtspsrc" + std::to_string(data->m_Id) + "\n").c_str()); 341 | data->rtspsrc = gst_element_factory_make ( "rtspsrc", ("rtspsrc" + std::to_string(data->m_Id)).c_str()); 342 | data->decode = gst_element_factory_make ( "decodebin", ("decodebin"+ std::to_string(data->m_Id)).c_str()); 343 | //data->mppdec = gst_element_factory_make ( "mppvideodec", "mppvideodec0"); 344 | data->tee = gst_element_factory_make ( "tee", ("tee"+ std::to_string(data->m_Id)).c_str()); 345 | 346 | data->queue_appsink = gst_element_factory_make ( "queue", ("queue_appsink"+ std::to_string(data->m_Id)).c_str()); 347 | data->appsink = gst_element_factory_make ( "appsink", ("app_sink"+ std::to_string(data->m_Id)).c_str()); 348 | 349 | if ( !data->pipeline || !data->rtspsrc | !data->decode || !data->tee || !data->queue_appsink || !data->appsink) { 350 | g_printerr("One element could not be created.\n"); 351 | } 352 | // Config appsink 353 | g_object_set (G_OBJECT (data->appsink), "sync", FALSE, NULL); 354 | /* Implement the allocation query using a pad probe. This probe will 355 | * adverstize support for GstVideoMeta, which avoid hardware accelerated 356 | * decoder that produce special strides and offsets from having to 357 | * copy the buffers. 358 | */ 359 | GstPad * apppad = gst_element_get_static_pad (data->appsink, "sink"); 360 | gst_pad_add_probe (apppad, GST_PAD_PROBE_TYPE_QUERY_DOWNSTREAM, 361 | appsink_query_cb, NULL, NULL); 362 | gst_object_unref (apppad); 363 | 364 | gst_base_sink_set_max_lateness (GST_BASE_SINK (data->appsink), 70 * GST_MSECOND); 365 | gst_base_sink_set_qos_enabled (GST_BASE_SINK (data->appsink), TRUE); 366 | 367 | g_object_set (G_OBJECT (data->appsink), "max-buffers", 1, NULL); 368 | 369 | gst_pad_add_probe (gst_element_get_static_pad (data->appsink, "sink"), 370 | GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, pad_probe, data, NULL); 371 | g_object_set (G_OBJECT (data->appsink), "emit-signals", TRUE, NULL ); 372 | // g_signal_connect ( G_OBJECT (data->appsink), "new-sample", G_CALLBACK (new_sample), data->pipeline); 373 | 374 | //create_uri(url,url_size, ip_address, port); 375 | g_print("rtsp_uri:%s\n",data->m_RtspUri); 376 | g_object_set(GST_OBJECT(data->rtspsrc), "location", data->m_RtspUri, NULL); 377 | g_object_set (GST_OBJECT (data->rtspsrc), "latency", 2000, NULL); 378 | // g_object_set (GST_OBJECT (data->rtspsrc), "timeout", 1000000, NULL); 379 | // g_object_set (GST_OBJECT (data->rtspsrc), "udp-reconnect", 1, NULL); 380 | // g_object_set (GST_OBJECT (data->rtspsrc), "retry", 1000, NULL); 381 | // g_object_set (GST_OBJECT (data->rtspsrc), "debug", 1, NULL); 382 | if (data->conn_Mode == 1) { 383 | g_object_set (GST_OBJECT (data->rtspsrc), "protocols", GST_RTSP_LOWER_TRANS_TCP, NULL); 384 | }else if ( data->conn_Mode == 2){ 385 | g_object_set (GST_OBJECT (data->rtspsrc), "protocols", GST_RTSP_LOWER_TRANS_UDP, NULL); 386 | } else { 387 | g_object_set (GST_OBJECT (data->rtspsrc), "protocols", GST_RTSP_LOWER_TRANS_UNKNOWN, NULL); 388 | } 389 | 390 | /** 391 | * GstRTSPLowerTrans: 392 | * @GST_RTSP_LOWER_TRANS_UNKNOWN: invalid transport flag 393 | * @GST_RTSP_LOWER_TRANS_UDP: stream data over UDP 394 | * @GST_RTSP_LOWER_TRANS_UDP_MCAST: stream data over UDP multicast 395 | * @GST_RTSP_LOWER_TRANS_TCP: stream data over TCP 396 | * @GST_RTSP_LOWER_TRANS_HTTP: stream data tunneled over HTTP. 397 | * @GST_RTSP_LOWER_TRANS_TLS: encrypt TCP and HTTP with TLS 398 | * 399 | * The different transport methods. 400 | */ 401 | // g_object_set (GST_OBJECT (data->rtspsrc), "protocols", GST_RTSP_LOWER_TRANS_HTTP, NULL); 402 | //"rtsp://:554/live/ch00_0" 403 | 404 | g_object_set (G_OBJECT (data->queue_appsink), "max-size-buffers", 1, NULL); 405 | // g_object_set (G_OBJECT (data->queue_appsink), "max-size-bytes", 1000, NULL); 406 | g_object_set (G_OBJECT (data->queue_appsink), "leaky", 2, NULL); 407 | gst_app_sink_set_max_buffers (GST_APP_SINK(data->appsink),1); 408 | gst_app_sink_set_buffer_list_support (GST_APP_SINK(data->appsink),FALSE); 409 | 410 | gst_bin_add_many(GST_BIN(data->pipeline), data->rtspsrc, data->decode, data->tee, NULL); 411 | // gst_bin_add_many(GST_BIN(data->pipeline), data->queue_appsink, data->appsink, NULL); 412 | // gst_bin_add_many(GST_BIN(data->pipeline), data->queue_appsink, data->videoconvert, data->appsink, NULL); 413 | gst_bin_add(GST_BIN(data->pipeline), data->queue_appsink); 414 | gst_bin_add(GST_BIN(data->pipeline), data->appsink);// queue -> rkximagesink || queue -> appsink 415 | if (!gst_element_link_many (data->queue_appsink, data->appsink, NULL)) { 416 | g_printerr ("Elements could not be linked.\n"); 417 | gst_object_unref (data->pipeline); 418 | return -1; 419 | } 420 | 421 | //tee -> queue1 -> queue2 422 | GstPad * queue2_video_pad = gst_element_get_static_pad ( data->queue_appsink, "sink"); 423 | GstPad * tee2_video_pad = gst_element_get_request_pad ( data->tee, "src_%u"); 424 | if (gst_pad_link ( tee2_video_pad, queue2_video_pad) != GST_PAD_LINK_OK) { 425 | g_printerr ("tee link queue error. \n"); 426 | gst_object_unref (data->pipeline); 427 | return -1; 428 | } 429 | gst_object_unref (queue2_video_pad); 430 | gst_object_unref (tee2_video_pad); 431 | 432 | g_signal_connect(data->rtspsrc, "pad-added", G_CALLBACK( on_src_decodebin_added), data); 433 | g_signal_connect(data->decode, "pad-added", G_CALLBACK( on_src_tee_added), data); 434 | 435 | data->bus = gst_pipeline_get_bus( GST_PIPELINE (data->pipeline)); 436 | gst_bus_add_watch (data->bus, bus_watch_cb, data); 437 | //gst_object_unref ( GST_OBJECT (bus)); 438 | 439 | // bus = gst_element_get_bus( GST_ELEMENT (data->appsink)); 440 | // gst_bus_add_watch (bus, (GstBusFunc) bus_uridecodebin_cb, data); 441 | // gst_object_unref ( GST_OBJECT (bus)); 442 | 443 | // start playing 444 | printf ("start playing \n"); 445 | gst_element_set_state (GST_ELEMENT(data->pipeline), GST_STATE_PLAYING); 446 | 447 | //g_main_loop_run (main_loop); 448 | // pthread_create (&data->gst_thread, NULL, video_frame_loop, data); 449 | 450 | return 1; 451 | } 452 | 453 | // destroy 454 | static void 455 | rtsp_destroy (struct CustomData *data) 456 | { 457 | if (data != NULL) { 458 | try{ 459 | if (data->loop != NULL) { 460 | g_main_loop_quit (data->loop); 461 | } 462 | 463 | if (data->pipeline != NULL) { 464 | gst_element_set_state (GST_ELEMENT(data->pipeline), GST_STATE_PAUSED); 465 | gst_element_set_state (GST_ELEMENT(data->pipeline), GST_STATE_NULL); 466 | } 467 | printf ("start gst_object_unref element \n"); 468 | if (data->bus != NULL) 469 | { 470 | gst_bus_remove_watch (data->bus); 471 | gst_object_unref ( GST_OBJECT (data->bus)); 472 | data->bus = NULL; 473 | } 474 | 475 | try{ 476 | gst_element_unlink (data->appsink, data->queue_appsink); 477 | gst_bin_remove_many(GST_BIN(data->pipeline), data->rtspsrc, data->decode, data->tee, NULL); 478 | gst_bin_remove_many(GST_BIN(data->pipeline), data->queue_appsink, data->appsink, NULL); 479 | data->rtspsrc = NULL; 480 | data->decode = NULL; 481 | data->tee = NULL; 482 | data->queue_appsink = NULL; 483 | data->appsink = NULL; 484 | } catch (...) 485 | { 486 | printf("rtsp_destroy error for gst_bin_remove_many \n"); 487 | } 488 | 489 | printf("finish bus unref \n"); 490 | if (data->pipeline != NULL) 491 | { 492 | gst_object_unref (data->pipeline); 493 | data->pipeline = NULL; 494 | } 495 | printf("finish pipeline unref \n"); 496 | if (data->loop != NULL) { 497 | g_main_loop_unref (data->loop); 498 | data->loop = NULL; 499 | } 500 | printf("finish loop unref \n"); 501 | //pthread_join(m_thread,NULL); 502 | } catch (...) 503 | { 504 | printf("rtsp_destroy error for gstreamer \n"); 505 | } 506 | 507 | try { 508 | if (data->m_RtspUri != NULL){ 509 | free (data->m_RtspUri); 510 | data->m_RtspUri = NULL; 511 | } 512 | } catch (...) 513 | { 514 | printf("mRtspUri free fail \n"); 515 | } 516 | 517 | printf("finish free m_RtspUri \n"); 518 | 519 | try { 520 | if (data->dst_buf != NULL) 521 | { 522 | free (data->dst_buf); 523 | data->dst_buf = NULL; 524 | } 525 | if (data->dst_output_buf != NULL) 526 | { 527 | free (data->dst_output_buf); 528 | data->dst_output_buf = NULL; 529 | } 530 | if (data->dst_resize_output_buf != NULL) 531 | { 532 | free (data->dst_resize_output_buf); 533 | data->dst_resize_output_buf = NULL; 534 | } 535 | if (data->dst_output_resize_buf != NULL) 536 | { 537 | free (data->dst_output_resize_buf); 538 | data->dst_output_resize_buf = NULL; 539 | } 540 | if (data->dst_resize_output_resize_buf != NULL) 541 | { 542 | free (data->dst_resize_output_resize_buf); 543 | data->dst_resize_output_resize_buf = NULL; 544 | } 545 | } catch (...) { 546 | printf("rtsp_destroy error for bufi \n"); 547 | } 548 | 549 | printf("rtsp_destory data = null \n"); 550 | data->isRun = STATUS_DISCONNECT; 551 | 552 | } else { 553 | printf("rtspDestory data== NULL \n"); 554 | } 555 | 556 | } 557 | 558 | RtspClient::RtspClient() { 559 | printf("rtsp rtspclient\n"); 560 | } 561 | 562 | RtspClient::~RtspClient() { 563 | printf("rtsp ~rtspclient!\n"); 564 | } 565 | 566 | int rtsp_check_url(char const* url) 567 | { 568 | #define RTSP_URL_PREFIX "rtsp://" 569 | 570 | int pos = sizeof(RTSP_URL_PREFIX)-1; 571 | 572 | // Parse URL, get configuration 573 | // the url MUST start with "rtsp://" 574 | if (strncmp(url, RTSP_URL_PREFIX, pos) != 0) { 575 | printf("URL not started with \"rtsp://\".\n"); 576 | return -1; 577 | } 578 | 579 | return 1; 580 | } 581 | 582 | // connect rtsp 583 | static void* connectrtsp(void *arg) { 584 | 585 | // int p = fork(); 586 | struct CustomData *data = (struct CustomData *)arg; 587 | 588 | printf("connectrtsp m_RtspUri %s \n", data->m_RtspUri); 589 | 590 | int ret = -1; 591 | try { 592 | ret = rtsp_check_url(data->m_RtspUri); 593 | } catch (...) { 594 | printf("connectrtsp mRtspUri check URI fail !"); 595 | data->isRun = STATUS_DISCONNECT; 596 | pthread_detach(pthread_self()); 597 | printf("pthread_exit rtsp_check_url exit\n"); 598 | pthread_exit(0); 599 | return NULL; 600 | } 601 | printf("connectrtsp m_RtspUri check ret %d \n", ret); 602 | if (ret == 1) { 603 | // gst init 604 | // gst_init (NULL, NULL); 605 | /** gst debug */ 606 | // GST_DEBUG_CATEGORY_INIT (rk_appsink_debug, "rk_appsink", 2, "App sink"); 607 | printf("mId %d mRtspUri %s \n", data->m_Id, data->m_RtspUri); 608 | 609 | data->isRun = STATUS_CONNECTING; 610 | int ret = 1; 611 | try { 612 | ret = rtsp_init (data); 613 | } catch (...){ 614 | data->isRun = STATUS_DISCONNECT; 615 | rtsp_destroy(data); 616 | pthread_detach(pthread_self()); 617 | printf("pthread_exit rtsp_init exit\n"); 618 | pthread_exit(0); 619 | return NULL; 620 | } 621 | if ( ret == -1) 622 | { 623 | data->isRun = STATUS_DISCONNECT; 624 | rtsp_destroy(data); 625 | pthread_detach(pthread_self()); 626 | printf("pthread_exit rtsp_init return fail exit\n"); 627 | pthread_exit(0); 628 | return NULL; 629 | } 630 | data->loop = g_main_loop_new (NULL, FALSE); 631 | g_main_loop_run (data->loop); 632 | 633 | printf("init exit mId %d \n", data->m_Id); 634 | data->isRun = STATUS_DISCONNECT; 635 | rtsp_destroy(data); 636 | pthread_detach(pthread_self()); 637 | printf("pthread_exit loop exit\n"); 638 | pthread_exit(0); 639 | return NULL; 640 | 641 | } 642 | 643 | data->isRun = STATUS_DISCONNECT; 644 | rtsp_destroy(data); 645 | pthread_detach(pthread_self()); 646 | printf("pthread_exit url check fail\n"); 647 | pthread_exit(0); 648 | return NULL; 649 | 650 | } 651 | 652 | bool 653 | RtspClient::changeURL(int id, const char* url, int conn_mode) { 654 | 655 | // g_print("RtspClient enable ! %d \n", id); 656 | if (this->m_data.isRun == STATUS_CONNECTED) { 657 | printf("enable fail, rtsp thread running \n"); 658 | return FALSE; 659 | } 660 | if (this->m_data.m_RtspUri != NULL){ 661 | free(this->m_data.m_RtspUri); 662 | this->m_data.m_RtspUri = NULL; 663 | } 664 | if (this->m_data.dst_buf != NULL){ 665 | free(this->m_data.dst_buf); 666 | this->m_data.dst_buf = NULL; 667 | } 668 | if (this->m_data.dst_output_buf != NULL){ 669 | free(this->m_data.dst_output_buf); 670 | this->m_data.dst_output_buf = NULL; 671 | } 672 | if (this->m_data.dst_resize_output_buf != NULL){ 673 | free(this->m_data.dst_resize_output_buf); 674 | this->m_data.dst_resize_output_buf = NULL; 675 | } 676 | if (this->m_data.dst_resize_output_resize_buf != NULL){ 677 | free(this->m_data.dst_resize_output_resize_buf); 678 | this->m_data.dst_resize_output_resize_buf = NULL; 679 | } 680 | if (this->m_data.dst_output_resize_buf != NULL){ 681 | free(this->m_data.dst_output_resize_buf); 682 | this->m_data.dst_output_resize_buf = NULL; 683 | } 684 | this->m_data.conn_Mode = conn_mode; 685 | size_t len = strlen(url) + 1; 686 | this->m_data.m_RtspUri = (char*)malloc(len); 687 | memset(this->m_data.m_RtspUri, 0, len); 688 | memcpy(this->m_data.m_RtspUri, url, len); 689 | printf("changeURL RtspClient mRtspUri %s \n",this->m_data.m_RtspUri); 690 | g_object_set(GST_OBJECT(this->m_data.rtspsrc), "location", this->m_data.m_RtspUri, NULL); 691 | g_object_set (GST_OBJECT (this->m_data.rtspsrc), "latency", 2000, NULL); 692 | //this->m_data->isRun = STATUS_CONNECTING; 693 | sleep(2); 694 | gst_element_set_state (GST_ELEMENT(this->m_data.pipeline), GST_STATE_PAUSED); 695 | gst_element_set_state (GST_ELEMENT(this->m_data.pipeline), GST_STATE_READY); 696 | gst_element_set_state (GST_ELEMENT(this->m_data.pipeline), GST_STATE_PLAYING); 697 | return TRUE; 698 | 699 | } 700 | 701 | bool 702 | RtspClient::reConnect(int id) { 703 | 704 | // g_print("RtspClient enable ! %d \n", id); 705 | if (this->m_data.isRun != STATUS_CONNECTED) { 706 | sleep(2); 707 | gst_element_set_state (GST_ELEMENT(this->m_data.pipeline), GST_STATE_PAUSED); 708 | gst_element_set_state (GST_ELEMENT(this->m_data.pipeline), GST_STATE_READY); 709 | gst_element_set_state (GST_ELEMENT(this->m_data.pipeline), GST_STATE_PLAYING); 710 | } else { 711 | printf("enable fail, reConnect rtsp thread running \n"); 712 | return FALSE; 713 | } 714 | return TRUE; 715 | } 716 | 717 | // start create sync 718 | bool 719 | RtspClient::enable(int id, const char* url, int conn_mode) { 720 | 721 | printf("RtspClient enable ! %d \n", id); 722 | 723 | if (this->m_data.isRun != STATUS_CONNECTING) { 724 | //this.m_data = g_new0 (struct CustomData, 1); 725 | this->m_data.m_Id = id; 726 | this->m_data.conn_Mode = conn_mode; 727 | size_t len = strlen(url) + 1; 728 | this->m_data.m_RtspUri = (char*)malloc(len); 729 | memset(this->m_data.m_RtspUri, 0, len); 730 | memcpy(this->m_data.m_RtspUri, url, len); 731 | printf("RtspClient mRtspUri %s \n",this->m_data.m_RtspUri); 732 | this->m_data.isRun = STATUS_CONNECTING; 733 | int ret = pthread_create(&m_thread, NULL, connectrtsp, &this->m_data); 734 | if ( ret != 0) { 735 | printf("enable fail, rtsp thread create fail \n"); 736 | return false; 737 | } 738 | } else { 739 | printf("enable fail, rtsp thread running \n"); 740 | return false; 741 | } 742 | 743 | return true; 744 | 745 | } 746 | 747 | // destroy instance 748 | void 749 | RtspClient::disable() { 750 | g_print("RtspClient start ~disable! mId %d \n",this->m_data.m_Id); 751 | // g_main_loop_quit(this->m_data->loop); 752 | if (this->m_data.isRun == STATUS_CONNECTED){ 753 | rtsp_destroy(&this->m_data); 754 | this->m_data.isRun = STATUS_DISCONNECT; 755 | } 756 | try{ 757 | pthread_cancel(this->m_thread); 758 | } catch (...) { 759 | printf("pthread_cancel error \n"); 760 | } 761 | pthread_join(this->m_thread, NULL); 762 | sleep(1); 763 | printf("RtspClient ~disable! end mId %d \n", this->m_data.m_Id); 764 | } 765 | 766 | // connect status 767 | int RtspClient::isConnect() 768 | { 769 | return this->m_data.isRun; 770 | } 771 | 772 | // read frame 773 | struct FrameData * 774 | RtspClient::read_Rga(int width, int height, int resize_width, int resize_height) { 775 | 776 | FrameData * data = new FrameData(); 777 | 778 | if ( this->m_data.isRun == STATUS_DISCONNECT){ 779 | data->isRun = STATUS_DISCONNECT; 780 | data->size = 0; 781 | return data; 782 | } 783 | 784 | try { 785 | 786 | data->isRun = this->m_data.isRun; 787 | data->size = 0; 788 | data->width = this->m_data.info.width; 789 | data->height = this->m_data.info.height; 790 | 791 | GstSample *samp; 792 | GstBuffer *buf; 793 | 794 | // samp = gst_app_sink_pull_sample (GST_APP_SINK (this->m_data->appsink)); 795 | samp = gst_app_sink_try_pull_sample (GST_APP_SINK (this->m_data.appsink), GST_SECOND * 3); // 1000 * 5 100000 796 | if (!samp) { 797 | GST_DEBUG ("got no appsink sample"); 798 | if (gst_app_sink_is_eos (GST_APP_SINK (this->m_data.appsink))){ 799 | GST_DEBUG ("eos"); 800 | //g_main_loop_quit(this->m_data.loop); 801 | gst_element_set_state (GST_ELEMENT(this->m_data.pipeline), GST_STATE_PAUSED); 802 | gst_element_set_state (GST_ELEMENT(this->m_data.pipeline), GST_STATE_READY); 803 | gst_element_set_state (GST_ELEMENT(this->m_data.pipeline), GST_STATE_PLAYING); 804 | sleep(2); 805 | data->isRun = STATUS_DISCONNECT; 806 | data->size = 0; 807 | this->m_data.frame=0; 808 | return data; 809 | }else{ 810 | GST_DEBUG ("gst_app_sink_try_pull_sample null"); 811 | gst_element_set_state (GST_ELEMENT(this->m_data.pipeline), GST_STATE_PAUSED); 812 | gst_element_set_state (GST_ELEMENT(this->m_data.pipeline), GST_STATE_READY); 813 | gst_element_set_state (GST_ELEMENT(this->m_data.pipeline), GST_STATE_PLAYING); 814 | sleep(2); 815 | data->isRun = STATUS_DISCONNECT; 816 | data->size = 0; 817 | this->m_data.frame=0; 818 | return data; 819 | } 820 | } 821 | 822 | buf = gst_sample_get_buffer (samp); 823 | 824 | // ** 825 | int ret; 826 | GstVideoMeta *meta = gst_buffer_get_video_meta (buf); 827 | guint nplanes = GST_VIDEO_INFO_N_PLANES (&(this->m_data.info)); 828 | // guint width, height; 829 | GstMapInfo map_info; 830 | gchar filename[128]; 831 | GstVideoFormat pixfmt; 832 | const char *pixfmt_str; 833 | 834 | pixfmt = GST_VIDEO_INFO_FORMAT (&(this->m_data.info)); 835 | pixfmt_str = gst_video_format_to_string (pixfmt); 836 | 837 | /* TODO: use the DMABUF directly */ 838 | // gst_buffer_map (buf, &map_info, GST_MAP_READ); 839 | // gst_buffer_map (buf, &map_info, GST_MAP_READ); 840 | if (!gst_buffer_map (buf, &map_info, (GstMapFlags)GST_MAP_READ)) 841 | { 842 | g_print ("gst_buffer_map() error! \n "); 843 | data->isRun = STATUS_DISCONNECT; 844 | data->size = 0; 845 | return data; 846 | } 847 | 848 | int source_width = GST_VIDEO_INFO_WIDTH (&(this->m_data.info)); 849 | int source_height = GST_VIDEO_INFO_HEIGHT (&(this->m_data.info)); 850 | 851 | if (this->m_data.last_time_width == 0 || this->m_data.last_time_hetight == 0) { 852 | this->m_data.last_time_width = source_width; 853 | this->m_data.last_time_hetight = source_height; 854 | } 855 | 856 | if (this->m_data.last_time_width != source_height && this->m_data.last_time_hetight != source_width) { 857 | if (this->m_data.dst_buf != NULL){ 858 | free(this->m_data.dst_buf); 859 | this->m_data.dst_buf = NULL; 860 | } 861 | if (this->m_data.dst_output_buf != NULL){ 862 | free(this->m_data.dst_output_buf); 863 | this->m_data.dst_output_buf = NULL; 864 | } 865 | if (this->m_data.dst_resize_output_buf != NULL){ 866 | free(this->m_data.dst_resize_output_buf); 867 | this->m_data.dst_resize_output_buf = NULL; 868 | } 869 | if (this->m_data.dst_resize_output_resize_buf != NULL){ 870 | free(this->m_data.dst_resize_output_resize_buf); 871 | this->m_data.dst_resize_output_resize_buf = NULL; 872 | } 873 | if (this->m_data.dst_output_resize_buf != NULL){ 874 | free(this->m_data.dst_output_resize_buf); 875 | this->m_data.dst_output_resize_buf = NULL; 876 | } 877 | } 878 | 879 | /* output some information at the beginning (= when the first frame is handled) */ 880 | if (this->m_data.frame == 0) { 881 | printf ("===================================\n"); 882 | printf ("GStreamer video stream information:\n"); 883 | printf (" size: %u x %u pixel\n", source_width, source_height); 884 | printf (" pixel format: %s number of planes: %u\n", pixfmt_str, nplanes); 885 | printf (" video meta found: %s\n", yesno (meta != NULL)); 886 | printf ("===================================\n"); 887 | printf ("mpp frame size : %d \n", map_info.size); 888 | } 889 | 890 | // g_print("mpp frame size : %d \n", map_info.size); 891 | //g_print("format %f \n",get_bpp_from_format(RK_FORMAT_YCrCb_420_SP)); 892 | 893 | // rga 894 | rga_buffer_t src; 895 | rga_buffer_t dst; 896 | rga_buffer_t dst_output; 897 | rga_buffer_t dst_resize_output; 898 | rga_buffer_t dst_two_resize_output; 899 | rga_buffer_t dst_two_output; 900 | 901 | // h265 256bit 1920 * 1080 == 2304 * 1080 902 | if (map_info.size == 3732480 || map_info.size == 4976640 || map_info.size == 3760128 ) { 903 | src = wrapbuffer_virtualaddr((char *) map_info.data, 2304, 1080, SRC_FORMAT); 904 | if (this->m_data.dst_buf == NULL){ 905 | this->m_data.dst_buf = (char*)malloc(2304*1080*get_bpp_from_format(DST_FORMAT)); 906 | } 907 | dst = wrapbuffer_virtualaddr(this->m_data.dst_buf, 2304, 1080, DST_FORMAT); 908 | if (this->m_data.dst_output_buf == NULL){ 909 | this->m_data.dst_output_buf = (char*)malloc(1920*1080*get_bpp_from_format(DST_FORMAT)); 910 | } 911 | dst_output = wrapbuffer_virtualaddr(this->m_data.dst_output_buf, 1920, 1080, DST_FORMAT); 912 | if (this->m_data.dst_resize_output_buf == NULL){ 913 | this->m_data.dst_resize_output_buf = (char*)malloc(width*height*get_bpp_from_format(DST_FORMAT)); 914 | } 915 | dst_resize_output = wrapbuffer_virtualaddr(this->m_data.dst_resize_output_buf, width, height,DST_FORMAT); 916 | if(src.width == 0 || dst.width == 0 || dst_output.width == 0) { 917 | printf("%s, %s\n", __FUNCTION__, imStrError()); 918 | // return data; 919 | } else { 920 | // g_print("1080 h265 imcvtcolor \n"); 921 | imcvtcolor(src, dst, src.format, dst.format); 922 | im_rect src_rect = {0, 0, 1920, 1080}; 923 | //g_print("imcrop %d",src_rect.width); 924 | imcrop(dst,dst_output,src_rect); 925 | 926 | imresize(dst_output,dst_resize_output); 927 | 928 | data->data = this->m_data.dst_resize_output_buf; 929 | data->size = width*height*get_bpp_from_format(DST_FORMAT); 930 | } 931 | 932 | } else 933 | // h264 16bit 1920 * 1080 == 1920 * 1088 934 | if (map_info.size == 3133440 || map_info.size == 4177920 ) { 935 | src = wrapbuffer_virtualaddr((char *) map_info.data, 1920, 1088, SRC_FORMAT); 936 | if (this->m_data.dst_buf == NULL){ 937 | this->m_data.dst_buf = (char*)malloc(1920*1088*get_bpp_from_format(DST_FORMAT)); 938 | } 939 | dst = wrapbuffer_virtualaddr(this->m_data.dst_buf, 1920, 1088, DST_FORMAT); 940 | if (this->m_data.dst_output_buf == NULL){ 941 | this->m_data.dst_output_buf = (char*)malloc(1920*1080*get_bpp_from_format(DST_FORMAT)); 942 | } 943 | dst_output = wrapbuffer_virtualaddr(this->m_data.dst_output_buf, 1920, 1080, DST_FORMAT); 944 | if (this->m_data.dst_resize_output_buf == NULL){ 945 | this->m_data.dst_resize_output_buf = (char*)malloc(width*height*get_bpp_from_format(DST_FORMAT)); 946 | } 947 | dst_resize_output = wrapbuffer_virtualaddr(this->m_data.dst_resize_output_buf, width, height, DST_FORMAT); 948 | if(src.width == 0 || dst.width == 0 || dst_output.width == 0) { 949 | printf("%s, %s\n", __FUNCTION__, imStrError()); 950 | // return data; 951 | } else { 952 | // g_print("1080 h264 imcvtcolor \n"); 953 | imcvtcolor(src, dst, src.format, dst.format); 954 | im_rect src_rect = {0, 0, 1920, 1080}; 955 | //g_print("imcrop %d",src_rect.width); 956 | imcrop(dst,dst_output,src_rect); 957 | 958 | imresize(dst_output,dst_resize_output); 959 | 960 | data->width = width; 961 | data->height = height; 962 | data->data = this->m_data.dst_resize_output_buf; 963 | data->size = width*height*get_bpp_from_format(DST_FORMAT); 964 | } 965 | 966 | } else 967 | // h265 2560 * 1440 256 2816 1584 968 | if (map_info.size == 6082560 || map_info.size == 8110080) { 969 | src = wrapbuffer_virtualaddr((char *) map_info.data, 2816, 1440, SRC_FORMAT); 970 | if (this->m_data.dst_buf == NULL){ 971 | this->m_data.dst_buf = (char*)malloc(2816*1440*get_bpp_from_format(DST_FORMAT)); 972 | } 973 | dst = wrapbuffer_virtualaddr(this->m_data.dst_buf, 2816, 1440, DST_FORMAT); 974 | if (this->m_data.dst_output_buf == NULL){ 975 | this->m_data.dst_output_buf = (char*)malloc(2560*1440*get_bpp_from_format(DST_FORMAT)); 976 | } 977 | dst_output = wrapbuffer_virtualaddr(this->m_data.dst_output_buf, 2560, 1440, DST_FORMAT); 978 | if (this->m_data.dst_resize_output_buf == NULL){ 979 | this->m_data.dst_resize_output_buf = (char*)malloc(width*height*get_bpp_from_format(DST_FORMAT)); 980 | } 981 | dst_resize_output = wrapbuffer_virtualaddr(this->m_data.dst_resize_output_buf, width, height, DST_FORMAT); 982 | if(src.width == 0 || dst.width == 0 || dst_output.width == 0) { 983 | printf("%s, %s\n", __FUNCTION__, imStrError()); 984 | // return data; 985 | } else { 986 | // g_print("1080 h264 imcvtcolor \n"); 987 | imcvtcolor(src, dst, src.format, dst.format); 988 | im_rect src_rect = {0, 0, 2560, 1440}; 989 | //g_print("imcrop %d",src_rect.width); 990 | imcrop(dst,dst_output,src_rect); 991 | 992 | imresize(dst_output,dst_resize_output); 993 | 994 | data->width = width; 995 | data->height = height; 996 | data->data = this->m_data.dst_resize_output_buf; 997 | data->size = width*height*get_bpp_from_format(DST_FORMAT); 998 | } 999 | 1000 | } else 1001 | //h265 640*480 768 * 480 1002 | if (map_info.size == 552960) { 1003 | src = wrapbuffer_virtualaddr((char *) map_info.data, 768, 480, SRC_FORMAT); 1004 | if (this->m_data.dst_buf == NULL){ 1005 | this->m_data.dst_buf = (char*)malloc(768*480*get_bpp_from_format(DST_FORMAT)); 1006 | } 1007 | dst = wrapbuffer_virtualaddr(this->m_data.dst_buf, 768, 480, DST_FORMAT); 1008 | if (this->m_data.dst_output_buf == NULL){ 1009 | this->m_data.dst_output_buf = (char*)malloc(640*480*get_bpp_from_format(DST_FORMAT)); 1010 | } 1011 | dst_output = wrapbuffer_virtualaddr(this->m_data.dst_output_buf, 640, 480, DST_FORMAT); 1012 | if (this->m_data.dst_resize_output_buf == NULL){ 1013 | this->m_data.dst_resize_output_buf = (char*)malloc(width*height*get_bpp_from_format(DST_FORMAT)); 1014 | } 1015 | dst_resize_output = wrapbuffer_virtualaddr(this->m_data.dst_resize_output_buf, width, height, DST_FORMAT); 1016 | if(src.width == 0 || dst.width == 0 || dst_output.width == 0) { 1017 | printf("%s, %s\n", __FUNCTION__, imStrError()); 1018 | // return data; 1019 | } else { 1020 | // g_print("1080 h264 imcvtcolor \n"); 1021 | imcvtcolor(src, dst, src.format, dst.format); 1022 | im_rect src_rect = {0, 0, 640, 480}; 1023 | //g_print("imcrop %d",src_rect.width); 1024 | imcrop(dst,dst_output,src_rect); 1025 | 1026 | imresize(dst_output,dst_resize_output); 1027 | 1028 | data->width = width; 1029 | data->height = height; 1030 | data->data = this->m_data.dst_resize_output_buf; 1031 | data->size = width*height*get_bpp_from_format(DST_FORMAT); 1032 | } 1033 | 1034 | } 1035 | else 1036 | // h265 h264 1037 | // supoort 1280*720 3840*2160 1038 | // h264 h265 3840*2160 12441600 12441600 1039 | { 1040 | 1041 | src = wrapbuffer_virtualaddr((char *) map_info.data, source_width, source_height, SRC_FORMAT); 1042 | if (this->m_data.dst_buf == NULL){ 1043 | this->m_data.dst_buf = (char*)malloc(source_width*source_height*get_bpp_from_format(DST_FORMAT)); 1044 | } 1045 | dst = wrapbuffer_virtualaddr(this->m_data.dst_buf, source_width, source_height, DST_FORMAT); 1046 | if (this->m_data.dst_output_buf == NULL){ 1047 | this->m_data.dst_output_buf = (char*)malloc(source_width*source_height*get_bpp_from_format(DST_FORMAT)); 1048 | } 1049 | dst_output = wrapbuffer_virtualaddr(this->m_data.dst_output_buf, source_width, source_height, DST_FORMAT); 1050 | if (this->m_data.dst_resize_output_buf == NULL){ 1051 | this->m_data.dst_resize_output_buf = (char*)malloc(width*height*get_bpp_from_format(DST_FORMAT)); 1052 | } 1053 | dst_resize_output = wrapbuffer_virtualaddr(this->m_data.dst_resize_output_buf, width, height, DST_FORMAT); 1054 | if(src.width == 0 || dst.width == 0 || dst_resize_output.width == 0) { 1055 | printf("%s, %s\n", __FUNCTION__, imStrError()); 1056 | // return data; 1057 | } else { 1058 | 1059 | imcvtcolor(src, dst, src.format, dst.format); 1060 | imresize(dst,dst_resize_output); 1061 | 1062 | data->width = width; 1063 | data->height = height; 1064 | data->data = this->m_data.dst_resize_output_buf; 1065 | data->size = width*height*get_bpp_from_format(DST_FORMAT); 1066 | 1067 | } 1068 | 1069 | } 1070 | 1071 | if (resize_width > 0 and resize_height > 0){ 1072 | // scale 640 resize data 1073 | if (this->m_data.dst_resize_output_resize_buf == NULL){ 1074 | this->m_data.dst_resize_output_resize_buf = (char*)malloc(resize_width*resize_height*get_bpp_from_format(DST_FORMAT)); 1075 | } 1076 | if (this->m_data.dst_output_resize_buf == NULL){ 1077 | this->m_data.dst_output_resize_buf = (char*)malloc(resize_width*resize_height*get_bpp_from_format(DST_FORMAT)); 1078 | } 1079 | dst_two_resize_output = wrapbuffer_virtualaddr(this->m_data.dst_resize_output_resize_buf, resize_width, resize_height, DST_FORMAT); 1080 | dst_two_output = wrapbuffer_virtualaddr(this->m_data.dst_output_resize_buf, resize_width, resize_height, DST_FORMAT); 1081 | if(src.width == 0 || dst.width == 0 || dst_two_resize_output.width == 0) { 1082 | printf("%s, %s\n", __FUNCTION__, imStrError()); 1083 | }else{ 1084 | imresize(dst, dst_two_resize_output, (double(resize_width)/width), (double(resize_height)/width)); 1085 | imtranslate(dst_two_resize_output, dst_two_output, 0, int((resize_height - (height * (double(resize_height)/width)))/2)); 1086 | data->data_resize = this->m_data.dst_output_resize_buf; 1087 | data->size_resize = resize_width * resize_height * get_bpp_from_format(DST_FORMAT); 1088 | } 1089 | } 1090 | 1091 | gst_buffer_unmap (buf, &map_info); 1092 | // ** 1093 | gst_sample_unref (samp); 1094 | 1095 | this->m_data.frame++; 1096 | 1097 | } catch (...) { 1098 | data->isRun = STATUS_DISCONNECT; 1099 | data->size = 0; 1100 | return data; 1101 | } 1102 | 1103 | return data; 1104 | 1105 | } 1106 | 1107 | // read frame 1108 | struct FrameData * 1109 | RtspClient::read_Opencv() { 1110 | 1111 | FrameData * data = new FrameData(); 1112 | 1113 | if ( this->m_data.isRun == STATUS_DISCONNECT){ 1114 | data->isRun = STATUS_DISCONNECT; 1115 | data->size = 0; 1116 | return data; 1117 | } 1118 | 1119 | try { 1120 | 1121 | data->isRun = this->m_data.isRun; 1122 | data->size = 0; 1123 | data->width = this->m_data.info.width; 1124 | data->height = this->m_data.info.height; 1125 | 1126 | GstSample *samp; 1127 | GstBuffer *buf; 1128 | 1129 | // samp = gst_app_sink_pull_sample (GST_APP_SINK (this->m_data->appsink)); 1130 | samp = gst_app_sink_try_pull_sample (GST_APP_SINK (this->m_data.appsink), GST_SECOND * 3); // 1000 * 5 100000 1131 | if (!samp) { 1132 | GST_DEBUG ("got no appsink sample"); 1133 | if (gst_app_sink_is_eos (GST_APP_SINK (this->m_data.appsink))){ 1134 | GST_DEBUG ("eos"); 1135 | //g_main_loop_quit(this->m_data.loop); 1136 | gst_element_set_state (GST_ELEMENT(this->m_data.pipeline), GST_STATE_PAUSED); 1137 | gst_element_set_state (GST_ELEMENT(this->m_data.pipeline), GST_STATE_READY); 1138 | gst_element_set_state (GST_ELEMENT(this->m_data.pipeline), GST_STATE_PLAYING); 1139 | sleep(2); 1140 | data->isRun = STATUS_DISCONNECT; 1141 | data->size = 0; 1142 | this->m_data.frame=0; 1143 | return data; 1144 | }else{ 1145 | GST_DEBUG ("gst_app_sink_try_pull_sample null"); 1146 | gst_element_set_state (GST_ELEMENT(this->m_data.pipeline), GST_STATE_PAUSED); 1147 | gst_element_set_state (GST_ELEMENT(this->m_data.pipeline), GST_STATE_READY); 1148 | gst_element_set_state (GST_ELEMENT(this->m_data.pipeline), GST_STATE_PLAYING); 1149 | sleep(2); 1150 | data->isRun = STATUS_DISCONNECT; 1151 | data->size = 0; 1152 | this->m_data.frame=0; 1153 | return data; 1154 | } 1155 | } 1156 | 1157 | buf = gst_sample_get_buffer (samp); 1158 | 1159 | // ** 1160 | int ret; 1161 | GstVideoMeta *meta = gst_buffer_get_video_meta (buf); 1162 | guint nplanes = GST_VIDEO_INFO_N_PLANES (&(this->m_data.info)); 1163 | // guint width, height; 1164 | GstMapInfo map_info; 1165 | gchar filename[128]; 1166 | GstVideoFormat pixfmt; 1167 | const char *pixfmt_str; 1168 | 1169 | pixfmt = GST_VIDEO_INFO_FORMAT (&(this->m_data.info)); 1170 | pixfmt_str = gst_video_format_to_string (pixfmt); 1171 | 1172 | /* TODO: use the DMABUF directly */ 1173 | // gst_buffer_map (buf, &map_info, GST_MAP_READ); 1174 | // gst_buffer_map (buf, &map_info, GST_MAP_READ); 1175 | if (!gst_buffer_map (buf, &map_info, (GstMapFlags)GST_MAP_READ)) 1176 | { 1177 | g_print ("gst_buffer_map() error! \n"); 1178 | data->isRun = STATUS_DISCONNECT; 1179 | data->size = 0; 1180 | return data; 1181 | } 1182 | 1183 | int source_width = GST_VIDEO_INFO_WIDTH (&(this->m_data.info)); 1184 | int source_height = GST_VIDEO_INFO_HEIGHT (&(this->m_data.info)); 1185 | 1186 | if (this->m_data.last_time_width == 0 || this->m_data.last_time_hetight == 0) { 1187 | this->m_data.last_time_width = source_width; 1188 | this->m_data.last_time_hetight = source_height; 1189 | } 1190 | 1191 | if (this->m_data.last_time_width != source_height && this->m_data.last_time_hetight != source_width) { 1192 | if (this->m_data.dst_buf != NULL){ 1193 | free(this->m_data.dst_buf); 1194 | this->m_data.dst_buf = NULL; 1195 | } 1196 | if (this->m_data.dst_output_buf != NULL){ 1197 | free(this->m_data.dst_output_buf); 1198 | this->m_data.dst_output_buf = NULL; 1199 | } 1200 | if (this->m_data.dst_resize_output_buf != NULL){ 1201 | free(this->m_data.dst_resize_output_buf); 1202 | this->m_data.dst_resize_output_buf = NULL; 1203 | } 1204 | if (this->m_data.dst_resize_output_resize_buf != NULL){ 1205 | free(this->m_data.dst_resize_output_resize_buf); 1206 | this->m_data.dst_resize_output_resize_buf = NULL; 1207 | } 1208 | if (this->m_data.dst_output_resize_buf != NULL){ 1209 | free(this->m_data.dst_output_resize_buf); 1210 | this->m_data.dst_output_resize_buf = NULL; 1211 | } 1212 | } 1213 | 1214 | /* output some information at the beginning (= when the first frame is handled) */ 1215 | if (this->m_data.frame == 0) { 1216 | printf ("===================================\n"); 1217 | printf ("GStreamer video stream information:\n"); 1218 | printf (" size: %u x %u pixel\n", source_width, source_height); 1219 | printf (" pixel format: %s number of planes: %u\n", pixfmt_str, nplanes); 1220 | printf (" video meta found: %s\n", yesno (meta != NULL)); 1221 | printf ("===================================\n"); 1222 | printf ("mpp frame size : %d \n", map_info.size); 1223 | } 1224 | 1225 | // g_print("mpp frame size : %d \n", map_info.size); 1226 | // g_print("format %f \n",get_bpp_from_format(RK_FORMAT_YCrCb_420_SP)); 1227 | 1228 | // opencv 1229 | // NV12/NV21说明: 1230 | // NV12: YYYYYYYY UVUV =>YUV420SP -> RK_FORMAT_YCbCr_420_SP 1231 | // NV21: YYYYYYYY VUVU =>YUV420SP -> RK_FORMAT_YCrCb_420_SP 1232 | 1233 | if (this->m_data.dst_buf == NULL){ 1234 | this->m_data.dst_buf = (char*)malloc(map_info.size); 1235 | } 1236 | memcpy(this->m_data.dst_buf, map_info.data, map_info.size); 1237 | 1238 | // TODO mpp没问题 1239 | // h265 256bit 1920 * 1080 == 2304 * 1080 1240 | if (map_info.size == 3732480 || map_info.size == 4976640) { 1241 | data->width = 2304; 1242 | data->height = 1080; 1243 | data->data = this->m_data.dst_buf; 1244 | data->size = map_info.size; 1245 | } else if (map_info.size == 3760128) { 1246 | data->width = 2304; 1247 | data->height = 1088; 1248 | data->data = this->m_data.dst_buf; 1249 | data->size = map_info.size; 1250 | } 1251 | else 1252 | // // h264 16bit 1920 * 1080 == 1920 * 1088 1253 | if (map_info.size == 3133440 || map_info.size == 4177920 ) { 1254 | data->width = 1920; 1255 | data->height = 1088; 1256 | data->data = this->m_data.dst_buf; 1257 | data->size = map_info.size; 1258 | } 1259 | else 1260 | // // h265 2560 * 1440 256 2816 1584 1261 | if (map_info.size == 6082560 || map_info.size == 8110080) { 1262 | data->width = 2816; 1263 | data->height = 1584; 1264 | data->data = this->m_data.dst_buf; 1265 | data->size = map_info.size; 1266 | } 1267 | else 1268 | // //h265 640*480 768 * 480 1269 | if (map_info.size == 552960) { 1270 | data->width = 640; 1271 | data->height = 480; 1272 | data->data = this->m_data.dst_buf; 1273 | data->size = map_info.size; 1274 | } else 1275 | // h265 h264 1276 | // supoort 1280*720 3840*2160 1277 | { 1278 | data->width = source_width; 1279 | data->height = source_height; 1280 | data->data = this->m_data.dst_buf; 1281 | data->size = map_info.size; 1282 | } 1283 | 1284 | gst_buffer_unmap (buf, &map_info); 1285 | // ** 1286 | gst_sample_unref (samp); 1287 | 1288 | this->m_data.frame++; 1289 | 1290 | } catch (...) { 1291 | data->isRun = STATUS_DISCONNECT; 1292 | data->size = 0; 1293 | return data; 1294 | } 1295 | 1296 | return data; 1297 | 1298 | } 1299 | --------------------------------------------------------------------------------