aac5773f
hucm
功能基本完成,接口待打磨
|
1
2
3
4
5
|
#include "FFNvDecoder.h"
#include<iostream>
#include <chrono>
#include <thread>
|
8c180bab
hucm
添加是否实时流判断
|
6
|
#include <fstream>
|
aac5773f
hucm
功能基本完成,接口待打磨
|
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
using namespace std;
// 参考博客: https://blog.csdn.net/qq_40116098/article/details/120704340
static AVPixelFormat get_hw_format(AVCodecContext *avctx, const AVPixelFormat *pix_fmts)
{
FFNvDecoder* _this = (FFNvDecoder*)avctx->opaque;
const AVPixelFormat *p;
for (p = pix_fmts; *p != -1; p++) {
if (*p == _this->getHwPixFmt())
return *p;
}
//cout << "Failed to get HW surface format";
return AV_PIX_FMT_NONE;
}
FFNvDecoder::FFNvDecoder()
{
// 初始化解码对象
fmt_ctx = nullptr;
avctx = nullptr;
m_bRunning = false;
stream = nullptr;
stream_index = -1;
hw_pix_fmt = AV_PIX_FMT_NONE;
name = "";
m_bPause = false;
|
8c180bab
hucm
添加是否实时流判断
|
40
|
m_bReal = true;
|
e96e6489
Hu Chunming
优化代码;添加isRunning函数
|
41
42
43
|
m_decode_thread = 0;
m_post_decode_thread = 0;
|
48330793
Hu Chunming
修正解码线程自然结束时解码器内存没...
|
44
45
|
m_bFinished = false;
|
aac5773f
hucm
功能基本完成,接口待打磨
|
46
47
48
49
50
51
52
|
}
FFNvDecoder::~FFNvDecoder()
{
}
|
e96e6489
Hu Chunming
优化代码;添加isRunning函数
|
53
|
bool FFNvDecoder::init(FFDecConfig& cfg)
|
7319ea36
Hu Chunming
多显卡设置
|
54
55
56
57
58
59
60
61
62
63
64
|
{
m_cfg = cfg;
fstream infile(cfg.uri);
if (infile.is_open()){
m_bReal = false;
infile.close();
}else {
m_bReal = true;
}
|
e96e6489
Hu Chunming
优化代码;添加isRunning函数
|
65
66
67
68
69
70
71
|
return init(cfg.uri.c_str(), cfg.gpuid.c_str(),cfg.force_tcp);
}
bool FFNvDecoder::init(const char* uri, const char* gpuid, bool force_tcp)
{
av_register_all();
avformat_network_init();
|
7319ea36
Hu Chunming
多显卡设置
|
72
73
74
75
|
// 打开输入视频文件
AVDictionary *options = nullptr;
av_dict_set( &options, "bufsize", "655360", 0 );
|
e96e6489
Hu Chunming
优化代码;添加isRunning函数
|
76
|
av_dict_set( &options, "rtsp_transport", force_tcp ? "tcp" : "udp", 0 );
|
7319ea36
Hu Chunming
多显卡设置
|
77
|
// av_dict_set( &options, "listen_timeout", "30", 0 ); // 单位为s
|
48330793
Hu Chunming
修正解码线程自然结束时解码器内存没...
|
78
|
av_dict_set( &options, "stimeout", "30000000", 0 ); // 单位为 百万分之一秒
|
7319ea36
Hu Chunming
多显卡设置
|
79
80
|
fmt_ctx = avformat_alloc_context();
|
e96e6489
Hu Chunming
优化代码;添加isRunning函数
|
81
|
const char* input_file = uri;
|
7319ea36
Hu Chunming
多显卡设置
|
82
|
if (avformat_open_input(&fmt_ctx, input_file, nullptr, &options) != 0) {
|
48330793
Hu Chunming
修正解码线程自然结束时解码器内存没...
|
83
|
cout << "Cannot open input file: " << input_file;
|
7319ea36
Hu Chunming
多显卡设置
|
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
return false;
}
// 查找流信息
if (avformat_find_stream_info(fmt_ctx, nullptr) < 0) {
cout << "Cannot find input stream information";
return false;
}
// 查找视频流信息
AVCodec *decoder = nullptr;
stream_index = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, &decoder, 0);
if (stream_index < 0) {
cout << "Cannot find a video stream in the input file";
return false;
}
|
7319ea36
Hu Chunming
多显卡设置
|
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
string cuvid_dec_name = string(decoder->name) + "_cuvid";
AVCodec *vcodec = avcodec_find_decoder_by_name(cuvid_dec_name.c_str());
if (!(avctx = avcodec_alloc_context3(vcodec)))
return (bool)AVERROR(ENOMEM);
// 得到视频流对象
stream = fmt_ctx->streams[stream_index];
if (avcodec_parameters_to_context(avctx, stream->codecpar) < 0)
return false;
avctx->opaque = this;
// 设置解码器管理器的像素格式回调函数
avctx->get_format = get_hw_format;
hw_pix_fmt = AV_PIX_FMT_CUDA;
// 打开解码器流
AVDictionary *op = nullptr;
|
e96e6489
Hu Chunming
优化代码;添加isRunning函数
|
119
|
av_dict_set( &op, "gpu", gpuid, 0 );
|
7319ea36
Hu Chunming
多显卡设置
|
120
121
122
123
124
125
126
127
|
if (avcodec_open2(avctx, vcodec, &op) < 0) {
cout << "Failed to open codec for stream" << stream_index;
return false;
}
return true;
}
|
aac5773f
hucm
功能基本完成,接口待打磨
|
128
129
130
131
132
133
134
135
136
137
138
139
|
void FFNvDecoder::start(){
m_bRunning = true;
pthread_create(&m_decode_thread,0,
[](void* arg)
{
FFNvDecoder* a=(FFNvDecoder*)arg;
a->decode_thread();
return (void*)0;
}
,this);
|
48330793
Hu Chunming
修正解码线程自然结束时解码器内存没...
|
140
141
142
143
144
145
146
|
}
void FFNvDecoder::decode_thread()
{
AVPacket* pkt ;
pkt = av_packet_alloc();
av_init_packet( pkt );
|
aac5773f
hucm
功能基本完成,接口待打磨
|
147
148
149
150
151
152
153
154
155
|
pthread_create(&m_post_decode_thread,0,
[](void* arg)
{
FFNvDecoder* a=(FFNvDecoder*)arg;
a->post_decode_thread();
return (void*)0;
}
,this);
|
aac5773f
hucm
功能基本完成,接口待打磨
|
156
157
158
|
while (m_bRunning)
{
|
8c180bab
hucm
添加是否实时流判断
|
159
|
if (!m_bReal)
|
aac5773f
hucm
功能基本完成,接口待打磨
|
160
|
{
|
8c180bab
hucm
添加是否实时流判断
|
161
162
163
164
165
|
if (m_bPause)
{
std::this_thread::sleep_for(std::chrono::milliseconds(3));
continue;
}
|
aac5773f
hucm
功能基本完成,接口待打磨
|
166
|
}
|
e41a52bb
Hu Chunming
1.优化数据读取线程;2. 添加A...
|
167
168
169
170
171
172
173
|
AVFrame * gpuFrame = mFrameQueue.getTail();
if (gpuFrame == nullptr)
{
std::this_thread::sleep_for(std::chrono::milliseconds(1));
continue;
}
|
aac5773f
hucm
功能基本完成,接口待打磨
|
174
175
176
177
178
179
180
181
182
183
184
185
186
|
int result = av_read_frame(fmt_ctx, pkt);
if (result == AVERROR_EOF)
{
cout << "Failed to read frame!" << endl;
break;
}
if (result < 0)
{
cout << "Failed to read frame!" << endl;
break;
}
|
f49bbf3d
Hu Chunming
修正pause逻辑;添加ignore
|
187
|
if (m_bReal)
|
8c180bab
hucm
添加是否实时流判断
|
188
189
190
191
192
193
194
195
196
|
{
if (m_bPause)
{
av_packet_unref(pkt);
std::this_thread::sleep_for(std::chrono::milliseconds(3));
continue;
}
}
|
aac5773f
hucm
功能基本完成,接口待打磨
|
197
198
199
200
201
|
if (stream_index == pkt->stream_index)
{
result = avcodec_send_packet(avctx, pkt);
if (result < 0)
{
|
7319ea36
Hu Chunming
多显卡设置
|
202
|
cout << "Failed to send pkt:" << result << endl;
|
aac5773f
hucm
功能基本完成,接口待打磨
|
203
204
205
|
continue;
}
|
aac5773f
hucm
功能基本完成,接口待打磨
|
206
207
208
209
210
211
212
213
|
result = avcodec_receive_frame(avctx, gpuFrame);
if (result == AVERROR(EAGAIN) || result == AVERROR_EOF || result < 0)
{
cout << "Failed to receive frame"<< endl;
continue;
}
mFrameQueue.addTail();
|
aac5773f
hucm
功能基本完成,接口待打磨
|
214
215
216
217
218
|
}
av_packet_unref(pkt);
}
m_bRunning = false;
|
48330793
Hu Chunming
修正解码线程自然结束时解码器内存没...
|
219
220
221
222
223
224
225
226
|
if (m_post_decode_thread != 0)
{
pthread_join(m_post_decode_thread,0);
}
decode_finished();
|
aac5773f
hucm
功能基本完成,接口待打磨
|
227
228
229
|
cout << "decode thread exited." << endl;
}
|
48330793
Hu Chunming
修正解码线程自然结束时解码器内存没...
|
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
|
void FFNvDecoder::decode_finished()
{
if (avctx)
{
if (avctx->hw_device_ctx)
{
av_buffer_unref(&avctx->hw_device_ctx);
}
avcodec_free_context(&avctx);
}
if (fmt_ctx)
{
avformat_close_input(&fmt_ctx);
}
m_bFinished = true;
}
|
aac5773f
hucm
功能基本完成,接口待打磨
|
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
|
void FFNvDecoder::post_decode_thread()
{
while (m_bRunning)
{
AVFrame * gpuFrame = mFrameQueue.getHead();
if (gpuFrame == nullptr)
{
std::this_thread::sleep_for(std::chrono::milliseconds(3));
continue;
}
post_decoded_cbk(m_userPtr, gpuFrame);
mFrameQueue.addHead();
}
cout << "post decode thread exited." << endl;
}
void FFNvDecoder::close()
{
m_bRunning=false;
|
e96e6489
Hu Chunming
优化代码;添加isRunning函数
|
271
272
273
|
if(m_decode_thread != 0){
pthread_join(m_decode_thread,0);
}
|
aac5773f
hucm
功能基本完成,接口待打磨
|
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
|
}
void FFNvDecoder::setName(string nm){
name = nm;
}
string FFNvDecoder::getName(){
return name;
}
AVPixelFormat FFNvDecoder::getHwPixFmt()
{
return hw_pix_fmt;
}
bool FFNvDecoder::isRunning()
{
return m_bRunning;
}
|
48330793
Hu Chunming
修正解码线程自然结束时解码器内存没...
|
294
295
296
297
298
|
bool FFNvDecoder::isFinished()
{
return m_bFinished;
}
|
aac5773f
hucm
功能基本完成,接口待打磨
|
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
|
bool FFNvDecoder::getResolution( int &width, int &height )
{
if (avctx != nullptr)
{
width = avctx->width;
height = avctx->height;
return true;
}
return false;
}
void FFNvDecoder::pause()
{
m_bPause = true;
}
void FFNvDecoder::resume()
{
m_bPause = false;
}
|