Commit ecb0badb0d3b7ba6b4175c174d63d78e118597e0
1 parent
92989af0
保存jpg图片
Showing
15 changed files
with
863 additions
and
23 deletions
.vscode/launch.json
@@ -6,7 +6,7 @@ | @@ -6,7 +6,7 @@ | ||
6 | "type": "cppdbg", | 6 | "type": "cppdbg", |
7 | "request": "launch", | 7 | "request": "launch", |
8 | "program": "${workspaceFolder}/bin/lib/test", | 8 | "program": "${workspaceFolder}/bin/lib/test", |
9 | - "args": ["rtsp","3", "30012"], | 9 | + "args": ["rtsp://192.168.10.4:8554/street","3", "30012"], |
10 | "stopAtEntry": false, | 10 | "stopAtEntry": false, |
11 | "cwd": "${workspaceFolder}/bin/lib", | 11 | "cwd": "${workspaceFolder}/bin/lib", |
12 | "environment": [], | 12 | "environment": [], |
@@ -55,6 +55,42 @@ | @@ -55,6 +55,42 @@ | ||
55 | "ignoreFailures": true | 55 | "ignoreFailures": true |
56 | } | 56 | } |
57 | ] | 57 | ] |
58 | + },{ | ||
59 | + "name": "save_tool", | ||
60 | + "type": "cppdbg", | ||
61 | + "request": "launch", | ||
62 | + "program": "${workspaceFolder}/bin/lib/save_tool", | ||
63 | + "args": ["rtsp://admin:ad123456@192.168.60.165:554/cam/realmonitor?channel=1&subtype=0"], | ||
64 | + "stopAtEntry": false, | ||
65 | + "cwd": "${workspaceFolder}/bin/lib", | ||
66 | + "environment": [], | ||
67 | + "externalConsole": false, | ||
68 | + "MIMode": "gdb", | ||
69 | + "setupCommands": [ | ||
70 | + { | ||
71 | + "description": "Enable pretty-printing for gdb", | ||
72 | + "text": "-enable-pretty-printing", | ||
73 | + "ignoreFailures": true | ||
74 | + } | ||
75 | + ] | ||
76 | + },{ | ||
77 | + "name": "gb28181", | ||
78 | + "type": "cppdbg", | ||
79 | + "request": "launch", | ||
80 | + "program": "${workspaceFolder}/bin/lib/test", | ||
81 | + "args": ["rtsp://192.168.10.4:8554/street","3", "30026","sipId"], | ||
82 | + "stopAtEntry": false, | ||
83 | + "cwd": "${workspaceFolder}/bin/lib", | ||
84 | + "environment": [], | ||
85 | + "externalConsole": false, | ||
86 | + "MIMode": "gdb", | ||
87 | + "setupCommands": [ | ||
88 | + { | ||
89 | + "description": "Enable pretty-printing for gdb", | ||
90 | + "text": "-enable-pretty-printing", | ||
91 | + "ignoreFailures": true | ||
92 | + } | ||
93 | + ] | ||
58 | } | 94 | } |
59 | ] | 95 | ] |
60 | } | 96 | } |
61 | \ No newline at end of file | 97 | \ No newline at end of file |
src/Makefile renamed to build/Makefile
@@ -16,6 +16,7 @@ TARGET= $(DEPEND_DIR)/lib/test | @@ -16,6 +16,7 @@ TARGET= $(DEPEND_DIR)/lib/test | ||
16 | 16 | ||
17 | SPDLOG_ROOT = $(THIRDPARTY_ROOT)/spdlog-1.9.2/release | 17 | SPDLOG_ROOT = $(THIRDPARTY_ROOT)/spdlog-1.9.2/release |
18 | JRTP_ROOT = $(THIRDPARTY_ROOT)/jrtp_export | 18 | JRTP_ROOT = $(THIRDPARTY_ROOT)/jrtp_export |
19 | +CURL_ROOT = $(THIRDPARTY_ROOT)/curl/bin | ||
19 | 20 | ||
20 | 21 | ||
21 | INCLUDE= -I $(DEPEND_DIR)/include \ | 22 | INCLUDE= -I $(DEPEND_DIR)/include \ |
@@ -26,13 +27,15 @@ INCLUDE= -I $(DEPEND_DIR)/include \ | @@ -26,13 +27,15 @@ INCLUDE= -I $(DEPEND_DIR)/include \ | ||
26 | -I $(SPDLOG_ROOT)/include \ | 27 | -I $(SPDLOG_ROOT)/include \ |
27 | -I $(SRC_ROOT)/gb28181 \ | 28 | -I $(SRC_ROOT)/gb28181 \ |
28 | -I $(JRTP_ROOT)/jrtplib/include/jrtplib3 \ | 29 | -I $(JRTP_ROOT)/jrtplib/include/jrtplib3 \ |
29 | - -I $(JRTP_ROOT)/jthread/include/jthread | 30 | + -I $(JRTP_ROOT)/jthread/include/jthread \ |
31 | + -I $(CURL_ROOT)/include \ | ||
30 | 32 | ||
31 | LIBSPATH= -L $(DEPEND_DIR)/lib -lavformat -lavcodec -lswscale -lavutil -lavfilter -lswresample -lavdevice \ | 33 | LIBSPATH= -L $(DEPEND_DIR)/lib -lavformat -lavcodec -lswscale -lavutil -lavfilter -lswresample -lavdevice \ |
32 | -L $(CUDA_ROOT)/lib64 -lcuda -lcudart -lnvcuvid -lcurand -lcublas -lnvjpeg \ | 34 | -L $(CUDA_ROOT)/lib64 -lcuda -lcudart -lnvcuvid -lcurand -lcublas -lnvjpeg \ |
33 | -L $(SPDLOG_ROOT) -l:libspdlog.a \ | 35 | -L $(SPDLOG_ROOT) -l:libspdlog.a \ |
34 | -L $(JRTP_ROOT)/jthread/lib -l:libjthread.a \ | 36 | -L $(JRTP_ROOT)/jthread/lib -l:libjthread.a \ |
35 | - -L $(JRTP_ROOT)/jrtplib/lib -l:libjrtp.a | 37 | + -L $(JRTP_ROOT)/jrtplib/lib -l:libjrtp.a \ |
38 | + -L $(CURL_ROOT)/lib -l:libcurl.a \ | ||
36 | 39 | ||
37 | CFLAGS= -g -fPIC -O0 $(INCLUDE) -pthread -lrt -lz -std=c++11 -fvisibility=hidden -Wl,-Bsymbolic -ldl | 40 | CFLAGS= -g -fPIC -O0 $(INCLUDE) -pthread -lrt -lz -std=c++11 -fvisibility=hidden -Wl,-Bsymbolic -ldl |
38 | # -DUNICODE -D_UNICODE | 41 | # -DUNICODE -D_UNICODE |
nv-codec-headers/Makefile
save_tool/Makefile
0 → 100644
1 | + | ||
2 | +XX = g++ | ||
3 | +NVCC = nvcc | ||
4 | + | ||
5 | +PROJECT_ROOT= /mnt/data/cmhu/FFNvDecoder | ||
6 | + | ||
7 | +DEPEND_DIR = $(PROJECT_ROOT)/bin | ||
8 | +SRC_ROOT = $(PROJECT_ROOT)/save_tool | ||
9 | +CUDA_ROOT = /usr/local/cuda | ||
10 | + | ||
11 | +TARGET= $(DEPEND_DIR)/lib/save_tool | ||
12 | + | ||
13 | + | ||
14 | +INCLUDE= -I $(DEPEND_DIR)/include \ | ||
15 | + -I $(CUDA_ROOT)/include \ | ||
16 | + -I $(SRC_ROOT)\ | ||
17 | + | ||
18 | +LIBSPATH= -L $(DEPEND_DIR)/lib -lavformat -lavcodec -lswscale -lavutil -lavfilter -lswresample -lavdevice \ | ||
19 | + -L $(CUDA_ROOT)/lib64 -lcudart -lcurand -lcublas -lnvjpeg \ | ||
20 | + -L /usr/lib/wsl/lib -lcuda -lnvcuvid\ | ||
21 | + | ||
22 | +CFLAGS= -g -fPIC -O0 $(INCLUDE) -pthread -lrt -lz -std=c++11 -fvisibility=hidden -Wl,-Bsymbolic -ldl | ||
23 | + # -DUNICODE -D_UNICODE | ||
24 | + | ||
25 | +NFLAGS_LIB=-g -c -shared -Xcompiler -fPIC -Xcompiler -fvisibility=hidden | ||
26 | +NFLAGS = $(NFLAGS_LIB) $(INCLUDE) -std=c++11 | ||
27 | + | ||
28 | +SRCS:=$(wildcard $(SRC_ROOT)/*.cpp) | ||
29 | +OBJS = $(patsubst %.cpp, %.o, $(notdir $(SRCS))) | ||
30 | + | ||
31 | +CU_SOURCES = $(wildcard ${SRC_ROOT}/*.cu) | ||
32 | +CU_OBJS = $(patsubst %.cu, %.o, $(notdir $(CU_SOURCES))) | ||
33 | + | ||
34 | + | ||
35 | +$(TARGET):$(OBJS) $(CU_OBJS) | ||
36 | + rm -f $(TARGET) | ||
37 | + $(XX) -o $@ $^ $(CFLAGS) $(LIBSPATH) $(LIBS) -Wwrite-strings | ||
38 | + rm -f *.o | ||
39 | + | ||
40 | +%.o:$(SRC_ROOT)/%.cpp | ||
41 | + $(XX) $(CFLAGS) -c $< | ||
42 | + | ||
43 | +%.o:$(SRC_ROOT)/%.cu | ||
44 | + @echo "#######################CU_OBJS:$@###############" | ||
45 | + $(NVCC) $(NFLAGS) -o $@ $< | ||
46 | + | ||
47 | +clean: | ||
48 | + rm -f *.o $(TARGET) | ||
49 | + | ||
50 | + |
save_tool/check_tool.cpp1
0 → 100644
1 | +#include"check_tool.h" | ||
2 | + | ||
3 | +extern "C" | ||
4 | +{ | ||
5 | + #include <libavcodec/avcodec.h> | ||
6 | + #include <libavdevice/avdevice.h> | ||
7 | + #include <libavformat/avformat.h> | ||
8 | + #include <libavfilter/avfilter.h> | ||
9 | + #include <libavutil/avutil.h> | ||
10 | + #include <libavutil/pixdesc.h> | ||
11 | + #include <libswscale/swscale.h> | ||
12 | + #include <libavutil/imgutils.h> | ||
13 | +} | ||
14 | + | ||
15 | +#include <chrono> | ||
16 | + | ||
17 | + | ||
18 | +static long long get_cur_time(){ | ||
19 | + // 获取操作系统当前时间点(精确到微秒) | ||
20 | + chrono::time_point<chrono::system_clock, chrono::milliseconds> tpMicro | ||
21 | + = chrono::time_point_cast<chrono::milliseconds>(chrono::system_clock::now()); | ||
22 | + // (微秒精度的)时间点 => (微秒精度的)时间戳 | ||
23 | + time_t currentTime = tpMicro.time_since_epoch().count(); | ||
24 | + | ||
25 | + return (long long )currentTime; | ||
26 | +} | ||
27 | + | ||
28 | +void save_pkt(const string& uri){ | ||
29 | + AVFormatContext* ifmt_ctx = nullptr; | ||
30 | + AVCodecContext* codec_ctx = nullptr; | ||
31 | + AVCodec *decoder = nullptr; | ||
32 | + AVCodec* codec = nullptr; | ||
33 | + AVPacket* pkt = nullptr; | ||
34 | + int video_index = -1; | ||
35 | + AVStream* i_video_stream = nullptr; | ||
36 | + SwsContext *img_convert_ctx = nullptr; | ||
37 | + uint8_t *buffer = nullptr; | ||
38 | + int numBytes = 0; | ||
39 | + | ||
40 | + long start_time = 0; | ||
41 | + long end_time = 0; | ||
42 | + long s_time = 0; | ||
43 | + long e_time = 0; | ||
44 | + long long sum = 0; | ||
45 | + double avg_time = 0.0; | ||
46 | + | ||
47 | + int sep = 0; | ||
48 | + | ||
49 | + AVFormatContext *o_fmt_ctx; | ||
50 | + AVStream *o_video_stream; | ||
51 | + | ||
52 | + const char *filename = "test.mp4"; | ||
53 | + | ||
54 | + | ||
55 | + avformat_network_init(); | ||
56 | + | ||
57 | + // 打开输入视频文件 | ||
58 | + AVDictionary *options = nullptr; | ||
59 | + av_dict_set( &options, "bufsize", "655360", 0 ); | ||
60 | + av_dict_set( &options, "rtsp_transport", "tcp", 0 ); | ||
61 | + // av_dict_set( &options, "listen_timeout", "30", 0 ); // 单位为s | ||
62 | + av_dict_set( &options, "stimeout", "30000000", 0 ); // 单位为 百万分之一秒 | ||
63 | + | ||
64 | + ///打开输入的流 | ||
65 | + ifmt_ctx = avformat_alloc_context(); | ||
66 | + int ret = avformat_open_input(&ifmt_ctx, uri.c_str(), nullptr, &options); | ||
67 | + if (ret != 0){ | ||
68 | + av_log(nullptr, AV_LOG_ERROR, "Couldn't open input stream ! \n"); | ||
69 | + goto end_flag ; | ||
70 | + } | ||
71 | + | ||
72 | + //查找流信息 | ||
73 | + if (avformat_find_stream_info(ifmt_ctx, nullptr) < 0){ | ||
74 | + av_log(nullptr, AV_LOG_ERROR, "Couldn't find stream information ! \n"); | ||
75 | + goto end_flag ; | ||
76 | + } | ||
77 | + | ||
78 | + // 查找视频流信息 | ||
79 | + video_index = av_find_best_stream(ifmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, &decoder, 0); | ||
80 | + if (video_index < 0) { | ||
81 | + av_log(nullptr, AV_LOG_ERROR, "Cannot find a video stream in the input file ! \n"); | ||
82 | + goto end_flag ; | ||
83 | + } | ||
84 | + | ||
85 | + //申请AVCodecContext | ||
86 | + codec_ctx = avcodec_alloc_context3(decoder); | ||
87 | + if (!codec_ctx){ | ||
88 | + goto end_flag ; | ||
89 | + } | ||
90 | + | ||
91 | + i_video_stream = ifmt_ctx->streams[video_index]; | ||
92 | + if(avcodec_parameters_to_context(codec_ctx, i_video_stream->codecpar) < 0){ | ||
93 | + goto end_flag ; | ||
94 | + } | ||
95 | + | ||
96 | + { | ||
97 | + av_log(nullptr, AV_LOG_INFO, "path: %s \n", ifmt_ctx->url); | ||
98 | + av_log(nullptr, AV_LOG_INFO, "format: %s \n", ifmt_ctx->iformat->name); | ||
99 | + const char* profile = avcodec_profile_name(codec_ctx->codec_id, codec_ctx->profile); | ||
100 | + av_log(nullptr, AV_LOG_INFO, "codec: %s(%s) \n", decoder->name, profile); | ||
101 | + const char* pix_fmt_name = av_get_pix_fmt_name(codec_ctx->pix_fmt); | ||
102 | + av_log(nullptr, AV_LOG_INFO, "pix_fmt_name: %s \n", pix_fmt_name); | ||
103 | + av_log(nullptr, AV_LOG_INFO, "width x height: %dX%d \n", i_video_stream->codecpar->width, i_video_stream->codecpar->height); | ||
104 | + | ||
105 | + av_log(NULL, AV_LOG_INFO, "frame_rate: %1.0f ", av_q2d(i_video_stream->r_frame_rate)); | ||
106 | + av_log(NULL, AV_LOG_INFO, " --> reference PPS: %f ms\n", 1/av_q2d(i_video_stream->r_frame_rate) * 1000); | ||
107 | + } | ||
108 | + | ||
109 | + | ||
110 | + avformat_alloc_output_context2(&o_fmt_ctx, NULL, NULL, filename); | ||
111 | + | ||
112 | + /* | ||
113 | + * since all input files are supposed to be identical (framerate, dimension, color format, ...) | ||
114 | + * we can safely set output codec values from first input file | ||
115 | + */ | ||
116 | + o_video_stream = avformat_new_stream(o_fmt_ctx, NULL); | ||
117 | + { | ||
118 | + AVCodecContext *c; | ||
119 | + c = o_video_stream->codec; | ||
120 | + c->bit_rate = 400000; | ||
121 | + c->codec_id = i_video_stream->codec->codec_id; | ||
122 | + c->codec_type = i_video_stream->codec->codec_type; | ||
123 | + c->time_base.num = i_video_stream->time_base.num; | ||
124 | + c->time_base.den = i_video_stream->time_base.den; | ||
125 | + fprintf(stderr, " = time_base.num = %d time_base.den = %d\n", c->time_base.num, c->time_base.den); | ||
126 | + c->width = i_video_stream->codec->width; | ||
127 | + c->height = i_video_stream->codec->height; | ||
128 | + c->pix_fmt = i_video_stream->codec->pix_fmt; | ||
129 | + printf(" = width: %d height: %d pix_fmt: %d\n", c->width, c->height, c->pix_fmt); | ||
130 | + c->flags = i_video_stream->codec->flags; | ||
131 | + c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; | ||
132 | + c->me_range = i_video_stream->codec->me_range; | ||
133 | + c->max_qdiff = i_video_stream->codec->max_qdiff; | ||
134 | + | ||
135 | + c->qmin = i_video_stream->codec->qmin; | ||
136 | + c->qmax = i_video_stream->codec->qmax; | ||
137 | + | ||
138 | + c->qcompress = i_video_stream->codec->qcompress; | ||
139 | + } | ||
140 | + | ||
141 | + avio_open(&o_fmt_ctx->pb, filename, AVIO_FLAG_WRITE); | ||
142 | + | ||
143 | + avformat_write_header(o_fmt_ctx, NULL); | ||
144 | + | ||
145 | + | ||
146 | + s_time = get_cur_time(); | ||
147 | + start_time = get_cur_time(); | ||
148 | + pkt = av_packet_alloc(); | ||
149 | + while (av_read_frame(ifmt_ctx, pkt) >= 0){ | ||
150 | + end_time = get_cur_time(); | ||
151 | + sum ++ ; | ||
152 | + sep ++ ; | ||
153 | + if(end_time - start_time > 1000){ | ||
154 | + avg_time = double(end_time - start_time) / sep; | ||
155 | + start_time = get_cur_time(); | ||
156 | + sep = 0; | ||
157 | + av_log(nullptr, AV_LOG_INFO, "PPS: %f ms\n", avg_time); | ||
158 | + } | ||
159 | + av_packet_unref(pkt); | ||
160 | + } | ||
161 | + | ||
162 | + e_time = get_cur_time(); | ||
163 | + avg_time = double(e_time - s_time) / sum; | ||
164 | + av_log(nullptr, AV_LOG_INFO, "TOOTAL PPS: %f ms\n", avg_time); | ||
165 | + | ||
166 | +end_flag: | ||
167 | + if (codec_ctx != nullptr){ | ||
168 | + avcodec_close(codec_ctx); | ||
169 | + avcodec_free_context(&codec_ctx); | ||
170 | + } | ||
171 | + | ||
172 | + if (ifmt_ctx != nullptr){ | ||
173 | + avformat_close_input(&ifmt_ctx); | ||
174 | + } | ||
175 | + | ||
176 | + if (pkt != nullptr){ | ||
177 | + av_packet_free(&pkt); | ||
178 | + } | ||
179 | +} | ||
0 | \ No newline at end of file | 180 | \ No newline at end of file |
save_tool/check_tool.h1
0 → 100644
save_tool/main.cpp
0 → 100644
1 | +#include"save_tool.h" | ||
2 | + | ||
3 | + | ||
4 | +#include<iostream> | ||
5 | + | ||
6 | +using namespace std; | ||
7 | + | ||
8 | + | ||
9 | + | ||
10 | +int main(int argc, char *argv[]) { | ||
11 | + printf("start \n"); | ||
12 | + if (argc != 2) { | ||
13 | + fprintf(stderr, "./xxx uri\n"); | ||
14 | + return -1; | ||
15 | + } | ||
16 | + | ||
17 | + char* uri = "rtsp://admin:ad123456@192.168.60.165:554/cam/realmonitor?channel=1&subtype=0"; | ||
18 | + | ||
19 | + cout << uri << endl; | ||
20 | + | ||
21 | + save_tool(uri); | ||
22 | + | ||
23 | + return 0; | ||
24 | +} | ||
0 | \ No newline at end of file | 25 | \ No newline at end of file |
save_tool/save_tool.cpp
0 → 100644
1 | +extern "C" | ||
2 | +{ | ||
3 | + #include <libavcodec/avcodec.h> | ||
4 | + #include <libavdevice/avdevice.h> | ||
5 | + #include <libavformat/avformat.h> | ||
6 | + #include <libavfilter/avfilter.h> | ||
7 | + #include <libavutil/avutil.h> | ||
8 | + #include <libavutil/pixdesc.h> | ||
9 | + #include <libswscale/swscale.h> | ||
10 | + #include <libavutil/imgutils.h> | ||
11 | +} | ||
12 | + | ||
13 | +#include <chrono> | ||
14 | +#include<string> | ||
15 | + | ||
16 | +using namespace std; | ||
17 | + | ||
18 | +bool bFirstFrame = false; | ||
19 | +long last_src_pts = 0; | ||
20 | +long last_pts = 0; | ||
21 | + | ||
22 | +void update_pts(AVPacket* pkt) { | ||
23 | + if (pkt->pts > 0) { | ||
24 | + if (bFirstFrame) { | ||
25 | + bFirstFrame = false; | ||
26 | + last_src_pts = pkt->pts; | ||
27 | + } | ||
28 | + int64_t pkt_pts = pkt->pts; | ||
29 | + pkt->pts = last_pts + (pkt_pts - last_src_pts); | ||
30 | + last_src_pts = pkt_pts; | ||
31 | + last_pts = pkt->pts; | ||
32 | + pkt->dts = pkt->pts; | ||
33 | + } | ||
34 | + else { | ||
35 | + if (bFirstFrame) { | ||
36 | + bFirstFrame = false; | ||
37 | + last_pts = 0; | ||
38 | + } | ||
39 | + pkt->pts = last_pts + 512; | ||
40 | + last_pts = pkt->pts; | ||
41 | + } | ||
42 | + | ||
43 | +} | ||
44 | + | ||
45 | +void *save_tool(const string uri) | ||
46 | +{ | ||
47 | + AVFormatContext *i_fmt_ctx; | ||
48 | + AVCodecContext* codec_ctx = nullptr; | ||
49 | + AVCodec *decoder = nullptr; | ||
50 | + AVStream *i_video_stream; | ||
51 | + int video_index; | ||
52 | + | ||
53 | + AVFormatContext *o_fmt_ctx; | ||
54 | + AVStream *o_video_stream; | ||
55 | + | ||
56 | + bool bStop = false; | ||
57 | + int frame_nums = 0; | ||
58 | + | ||
59 | + avcodec_register_all(); | ||
60 | + av_register_all(); | ||
61 | + avformat_network_init(); | ||
62 | + | ||
63 | + /* should set to NULL so that avformat_open_input() allocate a new one */ | ||
64 | + i_fmt_ctx = NULL; | ||
65 | + | ||
66 | + const char *filename = "2.mp4"; | ||
67 | + | ||
68 | + if (avformat_open_input(&i_fmt_ctx, uri.c_str(), NULL, NULL)!=0) | ||
69 | + { | ||
70 | + fprintf(stderr, " = could not open input file\n"); | ||
71 | + return nullptr; | ||
72 | + } | ||
73 | + | ||
74 | + if (avformat_find_stream_info(i_fmt_ctx, NULL)<0) | ||
75 | + { | ||
76 | + fprintf(stderr, " = could not find stream info\n"); | ||
77 | + return nullptr; | ||
78 | + } | ||
79 | + | ||
80 | + video_index = av_find_best_stream(i_fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, &decoder, 0); | ||
81 | + if (video_index < 0) { | ||
82 | + av_log(nullptr, AV_LOG_ERROR, "Cannot find a video stream in the input file ! \n"); | ||
83 | + return nullptr; | ||
84 | + } | ||
85 | + | ||
86 | + codec_ctx = avcodec_alloc_context3(decoder); | ||
87 | + if (!codec_ctx){ | ||
88 | + return nullptr; | ||
89 | + } | ||
90 | + | ||
91 | + i_video_stream = i_fmt_ctx->streams[video_index]; | ||
92 | + if(avcodec_parameters_to_context(codec_ctx, i_video_stream->codecpar) < 0){ | ||
93 | + return nullptr; | ||
94 | + } | ||
95 | + | ||
96 | + avformat_alloc_output_context2(&o_fmt_ctx, NULL, NULL, filename); | ||
97 | + | ||
98 | + o_video_stream = avformat_new_stream(o_fmt_ctx, NULL); | ||
99 | + { | ||
100 | + AVCodecContext *c; | ||
101 | + c = o_video_stream->codec; | ||
102 | + c->bit_rate = 400000; | ||
103 | + c->codec_id = i_video_stream->codec->codec_id; | ||
104 | + c->codec_type = i_video_stream->codec->codec_type; | ||
105 | + c->time_base.num = i_video_stream->time_base.num; | ||
106 | + c->time_base.den = i_video_stream->time_base.den; | ||
107 | + fprintf(stderr, " = time_base.num = %d time_base.den = %d\n", c->time_base.num, c->time_base.den); | ||
108 | + c->width = i_video_stream->codec->width; | ||
109 | + c->height = i_video_stream->codec->height; | ||
110 | + c->pix_fmt = i_video_stream->codec->pix_fmt; | ||
111 | + printf(" = width: %d height: %d pix_fmt: %d\n", c->width, c->height, c->pix_fmt); | ||
112 | + c->flags = i_video_stream->codec->flags; | ||
113 | + c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; | ||
114 | + c->me_range = i_video_stream->codec->me_range; | ||
115 | + c->max_qdiff = i_video_stream->codec->max_qdiff; | ||
116 | + | ||
117 | + c->qmin = i_video_stream->codec->qmin; | ||
118 | + c->qmax = i_video_stream->codec->qmax; | ||
119 | + | ||
120 | + c->qcompress = i_video_stream->codec->qcompress; | ||
121 | + } | ||
122 | + | ||
123 | + avio_open(&o_fmt_ctx->pb, filename, AVIO_FLAG_WRITE); | ||
124 | + | ||
125 | + avformat_write_header(o_fmt_ctx, NULL); | ||
126 | + | ||
127 | + AVPacket* i_pkt = av_packet_alloc(); | ||
128 | + av_init_packet(i_pkt); | ||
129 | + | ||
130 | + while (av_read_frame(i_fmt_ctx, i_pkt) >= 0){ | ||
131 | + | ||
132 | + update_pts(i_pkt); | ||
133 | + | ||
134 | + static int num = 1; | ||
135 | + printf(" = frame %d\n", num++); | ||
136 | + av_interleaved_write_frame(o_fmt_ctx, i_pkt); | ||
137 | + | ||
138 | + av_packet_unref(i_pkt); | ||
139 | + | ||
140 | + if(frame_nums > 750){ | ||
141 | + break; | ||
142 | + } | ||
143 | + frame_nums++; | ||
144 | + } | ||
145 | + | ||
146 | + av_packet_free(&i_pkt); | ||
147 | + | ||
148 | + avformat_close_input(&i_fmt_ctx); | ||
149 | + | ||
150 | + av_write_trailer(o_fmt_ctx); | ||
151 | + | ||
152 | + avcodec_close(o_fmt_ctx->streams[0]->codec); | ||
153 | + av_freep(&o_fmt_ctx->streams[0]->codec); | ||
154 | + av_freep(&o_fmt_ctx->streams[0]); | ||
155 | + | ||
156 | + avio_close(o_fmt_ctx->pb); | ||
157 | + av_free(o_fmt_ctx); | ||
158 | + | ||
159 | + printf("end. \n"); | ||
160 | +} | ||
0 | \ No newline at end of file | 161 | \ No newline at end of file |
save_tool/save_tool.h
0 → 100644
src/FFNvDecoderManager.cpp
@@ -40,6 +40,7 @@ AbstractDecoder* FFNvDecoderManager::createDecoder(MgrDecConfig config){ | @@ -40,6 +40,7 @@ AbstractDecoder* FFNvDecoderManager::createDecoder(MgrDecConfig config){ | ||
40 | if (bRet) | 40 | if (bRet) |
41 | { | 41 | { |
42 | dec->setName(config.name) ; | 42 | dec->setName(config.name) ; |
43 | + dec->setSnapTimeInterval(config.snap_time_interval); | ||
43 | decoderMap[config.name] = dec; | 44 | decoderMap[config.name] = dec; |
44 | 45 | ||
45 | LOG_INFO("[{}][{}]- 解码器初始化成功",config.name, config.cfg.uri); | 46 | LOG_INFO("[{}][{}]- 解码器初始化成功",config.name, config.cfg.uri); |
src/FFNvDecoderManager.h
@@ -12,6 +12,7 @@ struct MgrDecConfig | @@ -12,6 +12,7 @@ struct MgrDecConfig | ||
12 | DECODER_TYPE dec_type; // 解码器类型 | 12 | DECODER_TYPE dec_type; // 解码器类型 |
13 | FFDecConfig cfg; // 解码器配置 | 13 | FFDecConfig cfg; // 解码器配置 |
14 | string name{""}; // 解码器名称 | 14 | string name{""}; // 解码器名称 |
15 | + long snap_time_interval; // 定时抓拍时间间隔 | ||
15 | }; | 16 | }; |
16 | 17 | ||
17 | /** | 18 | /** |
src/FFSaveImg.cpp
0 → 100644
1 | +#include "FFSaveImg.h" | ||
2 | + | ||
3 | +extern "C" | ||
4 | +{ | ||
5 | + #include <libavcodec/avcodec.h> | ||
6 | + #include <libavdevice/avdevice.h> | ||
7 | + #include <libavformat/avformat.h> | ||
8 | + #include <libavfilter/avfilter.h> | ||
9 | + #include <libavutil/avutil.h> | ||
10 | + #include <libavutil/pixdesc.h> | ||
11 | + #include <libswscale/swscale.h> | ||
12 | + #include <libavutil/imgutils.h> | ||
13 | +} | ||
14 | + | ||
15 | +int saveJpg(AVFrame *pFrame, const char *out_file) { | ||
16 | + | ||
17 | + int width = pFrame->width; | ||
18 | + int height = pFrame->height; | ||
19 | + AVCodecContext *pCodecCtx = NULL; | ||
20 | + | ||
21 | + AVFormatContext *pFormatCtx = avformat_alloc_context(); | ||
22 | + // 设置输出文件格式 | ||
23 | + pFormatCtx->oformat = av_guess_format("mjpeg", NULL, NULL); | ||
24 | + | ||
25 | + // 创建并初始化输出AVIOContext | ||
26 | + if (avio_open(&pFormatCtx->pb, out_file, AVIO_FLAG_READ_WRITE) < 0) { | ||
27 | + printf("Couldn't open output file."); | ||
28 | + return -1; | ||
29 | + } | ||
30 | + | ||
31 | + // 构建一个新stream | ||
32 | + AVStream *video_st = avformat_new_stream(pFormatCtx, 0); | ||
33 | + if (video_st == NULL) { | ||
34 | + return -1; | ||
35 | + } | ||
36 | + | ||
37 | + pCodecCtx = video_st->codec; | ||
38 | + pCodecCtx->codec_id = pFormatCtx->oformat->video_codec; | ||
39 | + pCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO; | ||
40 | + pCodecCtx->pix_fmt = AV_PIX_FMT_YUVJ420P; | ||
41 | + pCodecCtx->width = width; | ||
42 | + pCodecCtx->height = height; | ||
43 | + | ||
44 | + pCodecCtx->time_base = (AVRational) {1, 25}; | ||
45 | + | ||
46 | + AVCodec *pCodec = avcodec_find_encoder(pCodecCtx->codec_id); | ||
47 | + | ||
48 | + if (!pCodec) { | ||
49 | + printf("Could not find encoder\n"); | ||
50 | + return -1; | ||
51 | + } | ||
52 | + | ||
53 | + if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) { | ||
54 | + printf("Could not open codec."); | ||
55 | + return -1; | ||
56 | + } | ||
57 | + | ||
58 | + int ret = avformat_write_header(pFormatCtx, NULL); | ||
59 | + if (ret < 0) { | ||
60 | + printf("write_header fail\n"); | ||
61 | + return -1; | ||
62 | + } | ||
63 | + | ||
64 | + AVPacket* pkt = av_packet_alloc(); | ||
65 | + av_init_packet(pkt); | ||
66 | + | ||
67 | + // 编码数据 | ||
68 | + ret = avcodec_send_frame(pCodecCtx, pFrame); | ||
69 | + if (ret < 0) { | ||
70 | + printf("Could not avcodec_send_frame."); | ||
71 | + return -1; | ||
72 | + } | ||
73 | + | ||
74 | + // 得到编码后数据 | ||
75 | + ret = avcodec_receive_packet(pCodecCtx, pkt); | ||
76 | + if (ret < 0) { | ||
77 | + printf("Could not avcodec_receive_packet"); | ||
78 | + return -1; | ||
79 | + } | ||
80 | + | ||
81 | + ret = av_write_frame(pFormatCtx, pkt); | ||
82 | + | ||
83 | + if (ret < 0) { | ||
84 | + printf("Could not av_write_frame"); | ||
85 | + return -1; | ||
86 | + } | ||
87 | + | ||
88 | + av_frame_free(&pFrame); | ||
89 | + av_packet_free(&pkt); | ||
90 | + | ||
91 | + //Write Trailer | ||
92 | + av_write_trailer(pFormatCtx); | ||
93 | + | ||
94 | + | ||
95 | + avcodec_close(pCodecCtx); | ||
96 | + avio_close(pFormatCtx->pb); | ||
97 | + avformat_free_context(pFormatCtx); | ||
98 | + | ||
99 | + return 0; | ||
100 | +} | ||
101 | + | ||
102 | +AVFrame* convert2yuv(int width, int height, unsigned char * rgbbuf, AVPixelFormat src_pix_fmt){ | ||
103 | + | ||
104 | + AVPixelFormat dst_pix_fmt = AV_PIX_FMT_YUV420P; | ||
105 | + | ||
106 | + AVFrame *pFrameYUV = av_frame_alloc(); | ||
107 | + uint8_t *out_buffer = new uint8_t[avpicture_get_size(dst_pix_fmt, width, height)]; | ||
108 | + | ||
109 | + avpicture_fill((AVPicture *)pFrameYUV, out_buffer, dst_pix_fmt, width, height); | ||
110 | + | ||
111 | + AVFrame *rgbFrame = av_frame_alloc(); | ||
112 | + | ||
113 | + avpicture_fill((AVPicture *)rgbFrame, rgbbuf, src_pix_fmt, width, height); | ||
114 | + | ||
115 | + SwsContext *sws_ctx = sws_getContext( | ||
116 | + width, height, src_pix_fmt, | ||
117 | + width, height, dst_pix_fmt, | ||
118 | + SWS_BILINEAR, NULL, NULL, NULL); | ||
119 | + | ||
120 | + sws_scale(sws_ctx, rgbFrame->data, rgbFrame->linesize, 0, height, pFrameYUV->data, pFrameYUV->linesize); | ||
121 | + sws_freeContext(sws_ctx); | ||
122 | + av_frame_free(&rgbFrame); | ||
123 | + | ||
124 | + pFrameYUV->width = width; | ||
125 | + pFrameYUV->height = height; | ||
126 | + pFrameYUV->format = dst_pix_fmt; | ||
127 | + | ||
128 | + return pFrameYUV; | ||
129 | +} | ||
130 | + | ||
131 | +void saveJpg(int width, int height, unsigned char * pData, string file_name){ | ||
132 | + AVFrame *pFrame = convert2yuv(width, height, pData, AV_PIX_FMT_BGR24); | ||
133 | + saveJpg(pFrame, file_name.c_str()); | ||
134 | +} | ||
0 | \ No newline at end of file | 135 | \ No newline at end of file |
src/FFSaveImg.h
0 → 100644
src/gb28181/FFGB28181Decoder.cpp
@@ -173,11 +173,11 @@ void FFGB28181Decoder::stream_callback(int videoType, char* data, int len, int i | @@ -173,11 +173,11 @@ void FFGB28181Decoder::stream_callback(int videoType, char* data, int len, int i | ||
173 | return; | 173 | return; |
174 | } | 174 | } |
175 | 175 | ||
176 | - AVPacket framePacket = {}; | ||
177 | - av_init_packet(&framePacket); | 176 | + AVPacket* pkt = av_packet_alloc(); |
177 | + av_init_packet(pkt); | ||
178 | 178 | ||
179 | - framePacket.size = len; | ||
180 | - framePacket.data = (uint8_t*)data; | 179 | + pkt->size = len; |
180 | + pkt->data = (uint8_t*)data; | ||
181 | 181 | ||
182 | if (m_pAVCodecCtx == nullptr) { | 182 | if (m_pAVCodecCtx == nullptr) { |
183 | LOG_INFO("frame data is zero --{}", m_dec_name); | 183 | LOG_INFO("frame data is zero --{}", m_dec_name); |
@@ -232,11 +232,12 @@ void FFGB28181Decoder::stream_callback(int videoType, char* data, int len, int i | @@ -232,11 +232,12 @@ void FFGB28181Decoder::stream_callback(int videoType, char* data, int len, int i | ||
232 | } | 232 | } |
233 | 233 | ||
234 | //开始解码 | 234 | //开始解码 |
235 | - int ret = avcodec_send_packet(m_pAVCodecCtx, &framePacket); | 235 | + int ret = avcodec_send_packet(m_pAVCodecCtx, pkt); |
236 | if (ret < 0) { | 236 | if (ret < 0) { |
237 | //send_exception(RunMessageType::E2002, e_msg); | 237 | //send_exception(RunMessageType::E2002, e_msg); |
238 | LOG_ERROR("Real stream视频解码失败,请检查视频设备{}: avcodec_send_packet failed. ret={}", m_dec_name, ret); | 238 | LOG_ERROR("Real stream视频解码失败,请检查视频设备{}: avcodec_send_packet failed. ret={}", m_dec_name, ret); |
239 | - av_packet_unref(&framePacket); | 239 | + av_packet_free(&pkt); |
240 | + pkt = nullptr; | ||
240 | return; | 241 | return; |
241 | } | 242 | } |
242 | 243 | ||
@@ -245,7 +246,8 @@ void FFGB28181Decoder::stream_callback(int videoType, char* data, int len, int i | @@ -245,7 +246,8 @@ void FFGB28181Decoder::stream_callback(int videoType, char* data, int len, int i | ||
245 | frameH = m_pAVCodecCtx->height; | 246 | frameH = m_pAVCodecCtx->height; |
246 | if (frameW <= 0 || frameH <= 0) { | 247 | if (frameW <= 0 || frameH <= 0) { |
247 | LOG_ERROR("[{}] frame W or H is error! ({},{})", m_dec_name, frameW, frameH); | 248 | LOG_ERROR("[{}] frame W or H is error! ({},{})", m_dec_name, frameW, frameH); |
248 | - av_packet_unref(&framePacket); | 249 | + av_packet_free(&pkt); |
250 | + pkt = nullptr; | ||
249 | return; | 251 | return; |
250 | } | 252 | } |
251 | } | 253 | } |
@@ -257,16 +259,20 @@ void FFGB28181Decoder::stream_callback(int videoType, char* data, int len, int i | @@ -257,16 +259,20 @@ void FFGB28181Decoder::stream_callback(int videoType, char* data, int len, int i | ||
257 | ret = avcodec_receive_frame(m_pAVCodecCtx, gpuFrame); | 259 | ret = avcodec_receive_frame(m_pAVCodecCtx, gpuFrame); |
258 | if ((ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) || ret < 0){ | 260 | if ((ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) || ret < 0){ |
259 | LOG_ERROR("{} - Failed to receive frame: {}", m_dec_name, ret); | 261 | LOG_ERROR("{} - Failed to receive frame: {}", m_dec_name, ret); |
260 | - av_packet_unref(&framePacket); | 262 | + av_packet_free(&pkt); |
263 | + pkt = nullptr; | ||
261 | av_frame_free(&gpuFrame); | 264 | av_frame_free(&gpuFrame); |
265 | + gpuFrame = nullptr; | ||
262 | return; | 266 | return; |
263 | } | 267 | } |
264 | 268 | ||
265 | - av_packet_unref(&framePacket); | 269 | + av_packet_free(&pkt); |
270 | + pkt = nullptr; | ||
266 | 271 | ||
267 | if (gpuFrame->width != frameW || gpuFrame->height != frameH){ | 272 | if (gpuFrame->width != frameW || gpuFrame->height != frameH){ |
268 | LOG_INFO("AVFrame is inconsistent: width is {}, height is {}; original frameW is {}, frameH is {}--{}", gpuFrame->width, gpuFrame->height, frameW, frameH , m_dec_name); | 273 | LOG_INFO("AVFrame is inconsistent: width is {}, height is {}; original frameW is {}, frameH is {}--{}", gpuFrame->width, gpuFrame->height, frameW, frameH , m_dec_name); |
269 | av_frame_free(&gpuFrame); | 274 | av_frame_free(&gpuFrame); |
275 | + gpuFrame = nullptr; | ||
270 | return; | 276 | return; |
271 | } | 277 | } |
272 | 278 | ||
@@ -275,6 +281,7 @@ void FFGB28181Decoder::stream_callback(int videoType, char* data, int len, int i | @@ -275,6 +281,7 @@ void FFGB28181Decoder::stream_callback(int videoType, char* data, int len, int i | ||
275 | mFrameQueue.push(gpuFrame); | 281 | mFrameQueue.push(gpuFrame); |
276 | }else{ | 282 | }else{ |
277 | av_frame_free(&gpuFrame); | 283 | av_frame_free(&gpuFrame); |
284 | + gpuFrame = nullptr; | ||
278 | } | 285 | } |
279 | m_queue_mutex.unlock(); | 286 | m_queue_mutex.unlock(); |
280 | } | 287 | } |
@@ -297,6 +304,7 @@ void FFGB28181Decoder::post_decode_thread(){ | @@ -297,6 +304,7 @@ void FFGB28181Decoder::post_decode_thread(){ | ||
297 | } | 304 | } |
298 | 305 | ||
299 | av_frame_free(&gpuFrame); | 306 | av_frame_free(&gpuFrame); |
307 | + gpuFrame = nullptr; | ||
300 | 308 | ||
301 | index++; | 309 | index++; |
302 | if(index >= 100000){ | 310 | if(index >= 100000){ |
src/main.cpp
@@ -12,6 +12,7 @@ | @@ -12,6 +12,7 @@ | ||
12 | 12 | ||
13 | #include <unistd.h> | 13 | #include <unistd.h> |
14 | 14 | ||
15 | +#include "FFSaveImg.h" | ||
15 | 16 | ||
16 | #ifdef _WIN32 | 17 | #ifdef _WIN32 |
17 | #include "Winsock2.h" | 18 | #include "Winsock2.h" |
@@ -24,6 +25,9 @@ | @@ -24,6 +25,9 @@ | ||
24 | 25 | ||
25 | #include "utiltools.hpp" | 26 | #include "utiltools.hpp" |
26 | 27 | ||
28 | +#include "curl/curl.h" | ||
29 | + | ||
30 | + | ||
27 | #define MIN_RTP_PORT 10000 | 31 | #define MIN_RTP_PORT 10000 |
28 | #define MAX_RTP_PORT 60000 | 32 | #define MAX_RTP_PORT 60000 |
29 | 33 | ||
@@ -155,10 +159,34 @@ int CheckCUDAProperty( int devId ) | @@ -155,10 +159,34 @@ int CheckCUDAProperty( int devId ) | ||
155 | return 0; | 159 | return 0; |
156 | } | 160 | } |
157 | 161 | ||
162 | +static long get_cur_time_ms() { | ||
163 | + chrono::time_point<chrono::system_clock, chrono::milliseconds> tpMicro | ||
164 | + = chrono::time_point_cast<chrono::milliseconds>(chrono::system_clock::now()); | ||
165 | + return tpMicro.time_since_epoch().count(); | ||
166 | +} | ||
167 | + | ||
158 | /** | 168 | /** |
159 | * 注意: gpuFrame 在解码器设置的显卡上,后续操作要十分注意这一点,尤其是多线程情况 | 169 | * 注意: gpuFrame 在解码器设置的显卡上,后续操作要十分注意这一点,尤其是多线程情况 |
160 | * */ | 170 | * */ |
161 | void postDecoded(const void * userPtr, AVFrame * gpuFrame){ | 171 | void postDecoded(const void * userPtr, AVFrame * gpuFrame){ |
172 | + | ||
173 | + // long first_time = get_cur_time_ms(); | ||
174 | + // long second_time = 0; | ||
175 | + // int a = 1; | ||
176 | + // while(true){ | ||
177 | + // a = a * 99; | ||
178 | + // if(a > 1000000){ | ||
179 | + // a = 1; | ||
180 | + // } | ||
181 | + // second_time = get_cur_time_ms(); | ||
182 | + // if(second_time - first_time > 100){ | ||
183 | + // break; | ||
184 | + // } | ||
185 | + // } | ||
186 | + // return ; | ||
187 | + | ||
188 | + // std::this_thread::sleep_for(std::chrono::milliseconds(100)); | ||
189 | + | ||
162 | AbstractDecoder* decoder = (AbstractDecoder*)userPtr; | 190 | AbstractDecoder* decoder = (AbstractDecoder*)userPtr; |
163 | if (decoder!= nullptr) | 191 | if (decoder!= nullptr) |
164 | { | 192 | { |
@@ -235,7 +263,8 @@ static int sum = 0; | @@ -235,7 +263,8 @@ static int sum = 0; | ||
235 | unsigned char *pHwData = nullptr; | 263 | unsigned char *pHwData = nullptr; |
236 | 264 | ||
237 | void postDecoded0(const void * userPtr, AVFrame * gpuFrame){ | 265 | void postDecoded0(const void * userPtr, AVFrame * gpuFrame){ |
238 | - // std::this_thread::sleep_for(std::chrono::milliseconds(30000)); | 266 | + |
267 | + std::this_thread::sleep_for(std::chrono::milliseconds(100)); | ||
239 | 268 | ||
240 | AbstractDecoder* decoder = (AbstractDecoder*)userPtr; | 269 | AbstractDecoder* decoder = (AbstractDecoder*)userPtr; |
241 | if (decoder!= nullptr) | 270 | if (decoder!= nullptr) |
@@ -287,12 +316,196 @@ void postDecoded0(const void * userPtr, AVFrame * gpuFrame){ | @@ -287,12 +316,196 @@ void postDecoded0(const void * userPtr, AVFrame * gpuFrame){ | ||
287 | } | 316 | } |
288 | } | 317 | } |
289 | 318 | ||
319 | +//get请求和post请求数据响应函数 | ||
320 | +size_t req_reply(void *ptr, size_t size, size_t nmemb, void *stream) | ||
321 | +{ | ||
322 | + //在注释的里面可以打印请求流,cookie的信息 | ||
323 | + //cout << "----->reply" << endl; | ||
324 | + string *str = (string*)stream; | ||
325 | + //cout << *str << endl; | ||
326 | + (*str).append((char*)ptr, size*nmemb); | ||
327 | + return size * nmemb; | ||
328 | +} | ||
329 | + | ||
330 | +//http POST请求 | ||
331 | +CURLcode curl_post_body_getVideoRealStream(const string &url, const string &postParams, string &response, string devid, string ip, string port) | ||
332 | +{ | ||
333 | + // curl初始化 | ||
334 | + CURL *curl = curl_easy_init(); | ||
335 | + // curl返回值 | ||
336 | + CURLcode res; | ||
337 | + if (curl) | ||
338 | + { | ||
339 | + // set params | ||
340 | + //设置curl的请求头 | ||
341 | + struct curl_slist* header_list = NULL; | ||
342 | + header_list = curl_slist_append(header_list, "User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko"); | ||
343 | + // header_list = curl_slist_append(header_list, "Content-Type:application/x-www-form-urlencoded; charset=UTF-8"); | ||
344 | + | ||
345 | + header_list = curl_slist_append(header_list, "Accept: application/json"); | ||
346 | + header_list = curl_slist_append(header_list, "Content-Type: application/json");//text/html | ||
347 | + header_list = curl_slist_append(header_list, "charsets: utf-8"); | ||
348 | + | ||
349 | + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_list); | ||
350 | + | ||
351 | + //不接收响应头数据0代表不接收 1代表接收 | ||
352 | + curl_easy_setopt(curl, CURLOPT_HEADER, 0); | ||
353 | + | ||
354 | + //设置请求为post请求 | ||
355 | + // curl_easy_setopt(curl, CURLOPT_POST, 1); | ||
356 | + curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST"); | ||
357 | + | ||
358 | + //设置请求的URL地址 | ||
359 | + curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); | ||
360 | + //设置post请求的参数 | ||
361 | + // curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postParams.c_str()); | ||
362 | + | ||
363 | + //设置ssl验证 | ||
364 | + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false); | ||
365 | + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false); | ||
366 | + | ||
367 | + //CURLOPT_VERBOSE的值为1时,会显示详细的调试信息 | ||
368 | + curl_easy_setopt(curl, CURLOPT_VERBOSE, 0); | ||
369 | + | ||
370 | + string strResult = "{ \ | ||
371 | + \"authinfo\": \"hisense|hisense123|201807311630\", \ | ||
372 | + \"method\": \"getVideoRealStream\", \ | ||
373 | + \"deviceId\": \""+devid+"\", \ | ||
374 | + \"streamFormat\": \"0\", \ | ||
375 | + \"recvIp\": \""+ip+"\", \ | ||
376 | + \"recvPort\": \""+port+"\", \ | ||
377 | + \"remark\": \"\", \ | ||
378 | + \"protocol\": \"1\" \ | ||
379 | + }"; | ||
380 | + | ||
381 | + curl_easy_setopt(curl,CURLOPT_POSTFIELDS,strResult.c_str()); | ||
382 | + | ||
383 | + curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL); | ||
384 | + | ||
385 | + //设置数据接收和写入函数 | ||
386 | + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, req_reply); | ||
387 | + curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response); | ||
388 | + | ||
389 | + curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); | ||
390 | + | ||
391 | + //设置超时时间 | ||
392 | + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 6); | ||
393 | + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 6); | ||
394 | + | ||
395 | + // 开启post请求 | ||
396 | + res = curl_easy_perform(curl); | ||
397 | + } | ||
398 | + //释放curl | ||
399 | + curl_easy_cleanup(curl); | ||
400 | + return res; | ||
401 | +} | ||
402 | + | ||
403 | +//http POST请求 | ||
404 | +CURLcode curl_post_body_stopVideoRealStream(const string &url, const string &postParams, string &response, string handleId) | ||
405 | +{ | ||
406 | + | ||
407 | + // curl初始化 | ||
408 | + CURL *curl = curl_easy_init(); | ||
409 | + // curl返回值 | ||
410 | + CURLcode res; | ||
411 | + if (curl) | ||
412 | + { | ||
413 | + // set params | ||
414 | + //设置curl的请求头 | ||
415 | + struct curl_slist* header_list = NULL; | ||
416 | + header_list = curl_slist_append(header_list, "User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko"); | ||
417 | + // header_list = curl_slist_append(header_list, "Content-Type:application/x-www-form-urlencoded; charset=UTF-8"); | ||
418 | + | ||
419 | + header_list = curl_slist_append(header_list, "Accept: application/json"); | ||
420 | + header_list = curl_slist_append(header_list, "Content-Type: application/json");//text/html | ||
421 | + header_list = curl_slist_append(header_list, "charsets: utf-8"); | ||
422 | + | ||
423 | + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_list); | ||
424 | + | ||
425 | + //不接收响应头数据0代表不接收 1代表接收 | ||
426 | + curl_easy_setopt(curl, CURLOPT_HEADER, 0); | ||
427 | + | ||
428 | + //设置请求为post请求 | ||
429 | + // curl_easy_setopt(curl, CURLOPT_POST, 1); | ||
430 | + curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST"); | ||
431 | + | ||
432 | + //设置请求的URL地址 | ||
433 | + curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); | ||
434 | + //设置post请求的参数 | ||
435 | + // curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postParams.c_str()); | ||
436 | + | ||
437 | + //设置ssl验证 | ||
438 | + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false); | ||
439 | + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false); | ||
440 | + | ||
441 | + //CURLOPT_VERBOSE的值为1时,会显示详细的调试信息 | ||
442 | + curl_easy_setopt(curl, CURLOPT_VERBOSE, 0); | ||
443 | + | ||
444 | + string strResult = "{ \ | ||
445 | + \"authinfo\": \"hisense|hisense123|201807311630\", \ | ||
446 | + \"method\": \"stopVideoRealStream\", \ | ||
447 | + \"handleId\": \""+ handleId + "\" \ | ||
448 | + }"; | ||
449 | + | ||
450 | + curl_easy_setopt(curl,CURLOPT_POSTFIELDS,strResult.c_str()); | ||
451 | + | ||
452 | + curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL); | ||
453 | + | ||
454 | + //设置数据接收和写入函数 | ||
455 | + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, req_reply); | ||
456 | + curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response); | ||
457 | + | ||
458 | + curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); | ||
459 | + | ||
460 | + //设置超时时间 | ||
461 | + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 6); | ||
462 | + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 6); | ||
463 | + | ||
464 | + // 开启post请求 | ||
465 | + res = curl_easy_perform(curl); | ||
466 | + } | ||
467 | + //释放curl | ||
468 | + curl_easy_cleanup(curl); | ||
469 | + return res; | ||
470 | +} | ||
471 | + | ||
290 | void decode_finished_cbk(const void* userPtr){ | 472 | void decode_finished_cbk(const void* userPtr){ |
291 | cout << "当前时间戳: " << UtilTools::get_cur_time_ms() << endl; | 473 | cout << "当前时间戳: " << UtilTools::get_cur_time_ms() << endl; |
292 | } | 474 | } |
293 | 475 | ||
476 | +string recv_port = "13012"; | ||
477 | + | ||
294 | bool decode_request_stream_cbk(const char* deviceId){ | 478 | bool decode_request_stream_cbk(const char* deviceId){ |
295 | - cout << "需在此请求流" << endl; | 479 | + // cout << "需在此请求流" << endl; |
480 | + | ||
481 | + string url_post = "http://172.16.6.129:7000/httpRequest"; | ||
482 | + string paramsLogin = "key1=value1&key2=value2"; | ||
483 | + string resPost; | ||
484 | + | ||
485 | + static string last_handleid = ""; | ||
486 | + if(!last_handleid.empty()){ | ||
487 | + auto res3 = curl_post_body_stopVideoRealStream(url_post, paramsLogin, resPost, last_handleid); | ||
488 | + if (res3 == CURLE_OK) | ||
489 | + { | ||
490 | + cout << resPost << endl; | ||
491 | + } | ||
492 | + } | ||
493 | + | ||
494 | + auto res = curl_post_body_getVideoRealStream(url_post, paramsLogin, resPost, deviceId, "172.16.6.129", recv_port); | ||
495 | + if (res == CURLE_OK) | ||
496 | + { | ||
497 | + cout << resPost << endl; | ||
498 | + | ||
499 | + size_t start = resPost.find_last_of(":") + 3; | ||
500 | + size_t end = resPost.find_last_of("\""); | ||
501 | + if (start == end){ | ||
502 | + return false; | ||
503 | + } | ||
504 | + last_handleid = resPost.substr(start,end - start); | ||
505 | + | ||
506 | + cout << last_handleid << endl; | ||
507 | + } | ||
508 | + | ||
296 | return true; | 509 | return true; |
297 | } | 510 | } |
298 | 511 | ||
@@ -301,7 +514,7 @@ bool decode_request_stream_cbk(const char* deviceId){ | @@ -301,7 +514,7 @@ bool decode_request_stream_cbk(const char* deviceId){ | ||
301 | // string test_uri = "/home/cmhu/data/output_1920x1080.mp4"; | 514 | // string test_uri = "/home/cmhu/data/output_1920x1080.mp4"; |
302 | // string test_uri = "rtsp://176.10.0.2:8554/stream"; | 515 | // string test_uri = "rtsp://176.10.0.2:8554/stream"; |
303 | // string test_uri = "/mnt/f/fiss/test_data/h265.mp4"; | 516 | // string test_uri = "/mnt/f/fiss/test_data/h265.mp4"; |
304 | -string test_uri = "rtsp://176.10.0.4:8554/stream"; | 517 | +string test_uri = "rtsp://192.168.10.4:8554/street"; |
305 | 518 | ||
306 | void createDecode(int index, const char* gpu_id){ | 519 | void createDecode(int index, const char* gpu_id){ |
307 | FFNvDecoderManager* pDecManager = FFNvDecoderManager::getInstance(); | 520 | FFNvDecoderManager* pDecManager = FFNvDecoderManager::getInstance(); |
@@ -312,6 +525,7 @@ void createDecode(int index, const char* gpu_id){ | @@ -312,6 +525,7 @@ void createDecode(int index, const char* gpu_id){ | ||
312 | config.cfg.decode_finished_cbk = decode_finished_cbk; | 525 | config.cfg.decode_finished_cbk = decode_finished_cbk; |
313 | config.cfg.force_tcp = true; | 526 | config.cfg.force_tcp = true; |
314 | config.dec_type = DECODER_TYPE_FFMPEG; | 527 | config.dec_type = DECODER_TYPE_FFMPEG; |
528 | + config.snap_time_interval = 100; | ||
315 | 529 | ||
316 | config.cfg.gpuid = gpu_id; | 530 | config.cfg.gpuid = gpu_id; |
317 | // if (index % 2 == 0) | 531 | // if (index % 2 == 0) |
@@ -333,10 +547,10 @@ void createDecode(int index, const char* gpu_id){ | @@ -333,10 +547,10 @@ void createDecode(int index, const char* gpu_id){ | ||
333 | pDecManager->startDecodeByName(config.name); | 547 | pDecManager->startDecodeByName(config.name); |
334 | } | 548 | } |
335 | 549 | ||
336 | -void createGB28181Decode(int index, char* gpu_id, int port){ | 550 | +void createGB28181Decode(char* devid, char* gpu_id, int port){ |
337 | FFNvDecoderManager* pDecManager = FFNvDecoderManager::getInstance(); | 551 | FFNvDecoderManager* pDecManager = FFNvDecoderManager::getInstance(); |
338 | MgrDecConfig config; | 552 | MgrDecConfig config; |
339 | - config.name = "dec" + to_string(index); | 553 | + config.name = devid; |
340 | config.cfg.uri = config.name; | 554 | config.cfg.uri = config.name; |
341 | config.cfg.post_decoded_cbk = postDecoded; | 555 | config.cfg.post_decoded_cbk = postDecoded; |
342 | config.cfg.decode_finished_cbk = decode_finished_cbk; | 556 | config.cfg.decode_finished_cbk = decode_finished_cbk; |
@@ -345,8 +559,11 @@ void createGB28181Decode(int index, char* gpu_id, int port){ | @@ -345,8 +559,11 @@ void createGB28181Decode(int index, char* gpu_id, int port){ | ||
345 | 559 | ||
346 | config.dec_type = DECODER_TYPE_GB28181; | 560 | config.dec_type = DECODER_TYPE_GB28181; |
347 | config.cfg.port = port;//allocRtpPort(); | 561 | config.cfg.port = port;//allocRtpPort(); |
348 | - | 562 | + |
349 | config.cfg.gpuid = gpu_id; | 563 | config.cfg.gpuid = gpu_id; |
564 | + config.snap_time_interval = 100; | ||
565 | + | ||
566 | + recv_port = to_string(port); | ||
350 | 567 | ||
351 | AbstractDecoder* decoder = pDecManager->createDecoder(config); | 568 | AbstractDecoder* decoder = pDecManager->createDecoder(config); |
352 | if (!decoder) | 569 | if (!decoder) |
@@ -366,10 +583,11 @@ void logFF(void *, int level, const char *fmt, va_list ap) | @@ -366,10 +583,11 @@ void logFF(void *, int level, const char *fmt, va_list ap) | ||
366 | 583 | ||
367 | int main(int argc, char* argv[]){ | 584 | int main(int argc, char* argv[]){ |
368 | 585 | ||
369 | - test_uri = "rtsp://admin:admin@123456@192.168.60.176:554/cam/realmonitor?channel=1&subtype=0";//argv[1]; | 586 | + test_uri = argv[1]; |
370 | char* gpuid = argv[2]; | 587 | char* gpuid = argv[2]; |
371 | int port = atoi(argv[3]); | 588 | int port = atoi(argv[3]); |
372 | - cout << test_uri << " gpu_id:" << gpuid << " port:" << port << endl; | 589 | + char* devId = argv[4]; |
590 | + cout << test_uri << " gpu_id:" << gpuid << " port:" << port << " devId:" << devId << endl; | ||
373 | 591 | ||
374 | // av_log_set_callback(&logFF); | 592 | // av_log_set_callback(&logFF); |
375 | 593 | ||
@@ -382,10 +600,20 @@ int main(int argc, char* argv[]){ | @@ -382,10 +600,20 @@ int main(int argc, char* argv[]){ | ||
382 | // cudaSetDevice(atoi(gpuid)); | 600 | // cudaSetDevice(atoi(gpuid)); |
383 | while (true) | 601 | while (true) |
384 | { | 602 | { |
385 | - std::this_thread::sleep_for(std::chrono::minutes(1)); | 603 | + std::this_thread::sleep_for(std::chrono::seconds(10)); |
386 | FFNvDecoderManager* pDecManager = FFNvDecoderManager::getInstance(); | 604 | FFNvDecoderManager* pDecManager = FFNvDecoderManager::getInstance(); |
387 | int count = pDecManager->count(); | 605 | int count = pDecManager->count(); |
388 | cout << "当前时间:" << UtilTools::get_cur_time_ms() << " 当前运行路数: " << pDecManager->count() << endl; | 606 | cout << "当前时间:" << UtilTools::get_cur_time_ms() << " 当前运行路数: " << pDecManager->count() << endl; |
607 | + vector<FFImgInfo*> vec_img = pDecManager->timing_snapshot_all(); | ||
608 | + for (auto imgInfo : vec_img){ | ||
609 | + auto task_id = imgInfo->dec_name; | ||
610 | + | ||
611 | + std::string fpath_ori = "./time_snapshot/" + task_id + "_" + std::to_string(imgInfo->timestamp) + ".jpg"; | ||
612 | + | ||
613 | + saveJpg(imgInfo->width, imgInfo->height, imgInfo->pData, fpath_ori.c_str()); | ||
614 | + | ||
615 | + pDecManager->releaseFFImgInfo(imgInfo); | ||
616 | + } | ||
389 | } | 617 | } |
390 | 618 | ||
391 | return (void*)0; | 619 | return (void*)0; |
@@ -413,7 +641,7 @@ int main(int argc, char* argv[]){ | @@ -413,7 +641,7 @@ int main(int argc, char* argv[]){ | ||
413 | break; | 641 | break; |
414 | case 'g': | 642 | case 'g': |
415 | case 'G': | 643 | case 'G': |
416 | - createGB28181Decode(i, gpuid, port); | 644 | + createGB28181Decode(devId, gpuid, port); |
417 | i++; | 645 | i++; |
418 | break; | 646 | break; |
419 | case 'r': | 647 | case 'r': |