aac5773f
hucm
功能基本完成,接口待打磨
|
1
|
#include "FFNvDecoder.h"
|
aac5773f
hucm
功能基本完成,接口待打磨
|
2
3
4
|
#include <chrono>
#include <thread>
|
8c180bab
hucm
添加是否实时流判断
|
5
|
#include <fstream>
|
aac5773f
hucm
功能基本完成,接口待打磨
|
6
|
|
f40cc409
Hu Chunming
优化显存占用。当前在3080显卡上...
|
7
8
|
#include "FFCuContextManager.h"
|
aac5773f
hucm
功能基本完成,接口待打磨
|
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
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;
}
|
d384f0e9
Hu Chunming
代码优化
|
24
|
av_log(nullptr, AV_LOG_ERROR, "Failed to get HW surface format. \n");
|
aac5773f
hucm
功能基本完成,接口待打磨
|
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
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
添加是否实时流判断
|
41
|
m_bReal = true;
|
e96e6489
Hu Chunming
优化代码;添加isRunning函数
|
42
43
44
|
m_decode_thread = 0;
m_post_decode_thread = 0;
|
48330793
Hu Chunming
修正解码线程自然结束时解码器内存没...
|
45
46
|
m_bFinished = false;
|
bc52e542
Hu Chunming
添加关键帧解码功能
|
47
|
m_dec_keyframe = false;
|
aac5773f
hucm
功能基本完成,接口待打磨
|
48
49
50
51
|
}
FFNvDecoder::~FFNvDecoder()
{
|
bc52e542
Hu Chunming
添加关键帧解码功能
|
52
|
m_dec_keyframe = false;
|
aac5773f
hucm
功能基本完成,接口待打磨
|
53
54
|
}
|
e96e6489
Hu Chunming
优化代码;添加isRunning函数
|
55
|
bool FFNvDecoder::init(FFDecConfig& cfg)
|
7319ea36
Hu Chunming
多显卡设置
|
56
57
58
59
60
61
62
63
64
65
66
|
{
m_cfg = cfg;
fstream infile(cfg.uri);
if (infile.is_open()){
m_bReal = false;
infile.close();
}else {
m_bReal = true;
}
|
e96e6489
Hu Chunming
优化代码;添加isRunning函数
|
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)
{
|
f40cc409
Hu Chunming
优化显存占用。当前在3080显卡上...
|
72
73
|
// av_log_set_level(AV_LOG_DEBUG);
|
e96e6489
Hu Chunming
优化代码;添加isRunning函数
|
74
|
avformat_network_init();
|
7319ea36
Hu Chunming
多显卡设置
|
75
76
77
78
|
// 打开输入视频文件
AVDictionary *options = nullptr;
av_dict_set( &options, "bufsize", "655360", 0 );
|
e96e6489
Hu Chunming
优化代码;添加isRunning函数
|
79
|
av_dict_set( &options, "rtsp_transport", force_tcp ? "tcp" : "udp", 0 );
|
7319ea36
Hu Chunming
多显卡设置
|
80
|
// av_dict_set( &options, "listen_timeout", "30", 0 ); // 单位为s
|
48330793
Hu Chunming
修正解码线程自然结束时解码器内存没...
|
81
|
av_dict_set( &options, "stimeout", "30000000", 0 ); // 单位为 百万分之一秒
|
7319ea36
Hu Chunming
多显卡设置
|
82
83
|
fmt_ctx = avformat_alloc_context();
|
e96e6489
Hu Chunming
优化代码;添加isRunning函数
|
84
|
const char* input_file = uri;
|
7319ea36
Hu Chunming
多显卡设置
|
85
|
if (avformat_open_input(&fmt_ctx, input_file, nullptr, &options) != 0) {
|
d384f0e9
Hu Chunming
代码优化
|
86
|
av_log(nullptr, AV_LOG_ERROR, "Cannot open input file: %s \n", input_file);
|
7319ea36
Hu Chunming
多显卡设置
|
87
88
89
90
91
|
return false;
}
// 查找流信息
if (avformat_find_stream_info(fmt_ctx, nullptr) < 0) {
|
d384f0e9
Hu Chunming
代码优化
|
92
|
av_log(nullptr, AV_LOG_ERROR, "Cannot find input stream information ! \n");
|
7319ea36
Hu Chunming
多显卡设置
|
93
94
95
96
97
98
99
|
return false;
}
// 查找视频流信息
AVCodec *decoder = nullptr;
stream_index = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, &decoder, 0);
if (stream_index < 0) {
|
d384f0e9
Hu Chunming
代码优化
|
100
|
av_log(nullptr, AV_LOG_ERROR, "Cannot find a video stream in the input file ! \n");
|
7319ea36
Hu Chunming
多显卡设置
|
101
102
103
|
return false;
}
|
7319ea36
Hu Chunming
多显卡设置
|
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
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;
|
f40cc409
Hu Chunming
优化显存占用。当前在3080显卡上...
|
120
|
FFCuContextManager* pCtxMgr = FFCuContextManager::getInstance();
|
d384f0e9
Hu Chunming
代码优化
|
121
122
123
124
125
126
127
|
AVBufferRef *hw_device_ctx = pCtxMgr->getCuCtx(gpuid);
if(nullptr == hw_device_ctx){
av_log(nullptr, AV_LOG_ERROR, "create CUDA context failed ! \n");
return false;
}
avctx->hw_device_ctx = av_buffer_ref(hw_device_ctx);
|
f40cc409
Hu Chunming
优化显存占用。当前在3080显卡上...
|
128
129
130
131
132
|
if (nullptr == avctx->hw_device_ctx)
{
return false;
}
|
7319ea36
Hu Chunming
多显卡设置
|
133
134
|
// 打开解码器流
AVDictionary *op = nullptr;
|
e96e6489
Hu Chunming
优化代码;添加isRunning函数
|
135
|
av_dict_set( &op, "gpu", gpuid, 0 );
|
d384f0e9
Hu Chunming
代码优化
|
136
|
// av_dict_set( &op, "surfaces", "10", 0 );
|
7319ea36
Hu Chunming
多显卡设置
|
137
|
if (avcodec_open2(avctx, vcodec, &op) < 0) {
|
d384f0e9
Hu Chunming
代码优化
|
138
|
av_log(nullptr, AV_LOG_ERROR, "Failed to open codec for stream ! \n");
|
7319ea36
Hu Chunming
多显卡设置
|
139
140
141
142
143
144
|
return false;
}
return true;
}
|
0573bd98
Hu Chunming
优化代码;添加注释
|
145
146
147
148
149
150
151
|
bool FFNvDecoder::isSurport(FFDecConfig& cfg)
{
bool bRet = init(cfg);
decode_finished();
return bRet;
}
|
aac5773f
hucm
功能基本完成,接口待打磨
|
152
153
154
155
156
157
158
159
160
161
162
163
|
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
修正解码线程自然结束时解码器内存没...
|
164
165
|
}
|
bc52e542
Hu Chunming
添加关键帧解码功能
|
166
167
|
static long long get_cur_time(){
// 获取操作系统当前时间点(精确到微秒)
|
d384f0e9
Hu Chunming
代码优化
|
168
169
|
chrono::time_point<chrono::system_clock, chrono::milliseconds> tpMicro
= chrono::time_point_cast<chrono::milliseconds>(chrono::system_clock::now());
|
bc52e542
Hu Chunming
添加关键帧解码功能
|
170
|
// (微秒精度的)时间点 => (微秒精度的)时间戳
|
d384f0e9
Hu Chunming
代码优化
|
171
|
time_t currentTime = tpMicro.time_since_epoch().count();
|
bc52e542
Hu Chunming
添加关键帧解码功能
|
172
|
|
d384f0e9
Hu Chunming
代码优化
|
173
|
return (long long )currentTime;
|
bc52e542
Hu Chunming
添加关键帧解码功能
|
174
175
|
}
|
48330793
Hu Chunming
修正解码线程自然结束时解码器内存没...
|
176
177
178
179
180
|
void FFNvDecoder::decode_thread()
{
AVPacket* pkt ;
pkt = av_packet_alloc();
av_init_packet( pkt );
|
aac5773f
hucm
功能基本完成,接口待打磨
|
181
182
183
184
185
186
187
188
189
|
pthread_create(&m_post_decode_thread,0,
[](void* arg)
{
FFNvDecoder* a=(FFNvDecoder*)arg;
a->post_decode_thread();
return (void*)0;
}
,this);
|
aac5773f
hucm
功能基本完成,接口待打磨
|
190
|
|
bc52e542
Hu Chunming
添加关键帧解码功能
|
191
192
|
// long start_time = get_cur_time();
|
aac5773f
hucm
功能基本完成,接口待打磨
|
193
194
|
while (m_bRunning)
{
|
8c180bab
hucm
添加是否实时流判断
|
195
|
if (!m_bReal)
|
aac5773f
hucm
功能基本完成,接口待打磨
|
196
|
{
|
8c180bab
hucm
添加是否实时流判断
|
197
198
199
200
201
|
if (m_bPause)
{
std::this_thread::sleep_for(std::chrono::milliseconds(3));
continue;
}
|
aac5773f
hucm
功能基本完成,接口待打磨
|
202
|
}
|
e41a52bb
Hu Chunming
1.优化数据读取线程;2. 添加A...
|
203
204
205
206
207
208
209
|
AVFrame * gpuFrame = mFrameQueue.getTail();
if (gpuFrame == nullptr)
{
std::this_thread::sleep_for(std::chrono::milliseconds(1));
continue;
}
|
aac5773f
hucm
功能基本完成,接口待打磨
|
210
211
|
int result = av_read_frame(fmt_ctx, pkt);
|
3c7e3e11
Hu Chunming
1.修改日志
|
212
|
if (result == AVERROR_EOF || result < 0)
|
aac5773f
hucm
功能基本完成,接口待打磨
|
213
|
{
|
d384f0e9
Hu Chunming
代码优化
|
214
|
av_log(nullptr, AV_LOG_ERROR, "Failed to read frame! \n");
|
aac5773f
hucm
功能基本完成,接口待打磨
|
215
216
217
|
break;
}
|
bc52e542
Hu Chunming
添加关键帧解码功能
|
218
219
220
221
222
|
if (m_dec_keyframe && !(pkt->flags & AV_PKT_FLAG_KEY)) {
av_packet_unref(pkt);
continue;
}
|
f49bbf3d
Hu Chunming
修正pause逻辑;添加ignore
|
223
|
if (m_bReal)
|
8c180bab
hucm
添加是否实时流判断
|
224
225
226
227
228
229
230
231
232
|
{
if (m_bPause)
{
av_packet_unref(pkt);
std::this_thread::sleep_for(std::chrono::milliseconds(3));
continue;
}
}
|
3c7e3e11
Hu Chunming
1.修改日志
|
233
|
if (stream_index == pkt->stream_index){
|
aac5773f
hucm
功能基本完成,接口待打磨
|
234
|
result = avcodec_send_packet(avctx, pkt);
|
3c7e3e11
Hu Chunming
1.修改日志
|
235
|
if (result < 0){
|
d384f0e9
Hu Chunming
代码优化
|
236
|
av_log(nullptr, AV_LOG_ERROR, "Failed to send pkt: %d \n",result);
|
aac5773f
hucm
功能基本完成,接口待打磨
|
237
238
239
|
continue;
}
|
aac5773f
hucm
功能基本完成,接口待打磨
|
240
|
result = avcodec_receive_frame(avctx, gpuFrame);
|
3c7e3e11
Hu Chunming
1.修改日志
|
241
|
if ((result == AVERROR(EAGAIN) || result == AVERROR_EOF) || result < 0){
|
d384f0e9
Hu Chunming
代码优化
|
242
|
av_log(nullptr, AV_LOG_ERROR, "Failed to receive frame: %d \n",result);
|
aac5773f
hucm
功能基本完成,接口待打磨
|
243
244
245
246
|
continue;
}
mFrameQueue.addTail();
|
aac5773f
hucm
功能基本完成,接口待打磨
|
247
248
249
250
|
}
av_packet_unref(pkt);
}
|
3c7e3e11
Hu Chunming
1.修改日志
|
251
252
253
254
255
256
257
258
|
// 队列中没有数据了再结束
while (mFrameQueue.length() > 0){
if(!m_bRunning){
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
|
aac5773f
hucm
功能基本完成,接口待打磨
|
259
|
m_bRunning = false;
|
48330793
Hu Chunming
修正解码线程自然结束时解码器内存没...
|
260
|
|
bc52e542
Hu Chunming
添加关键帧解码功能
|
261
262
263
264
|
// long end_time = get_cur_time();
// cout << "解码用时:" << end_time - start_time << endl;
|
48330793
Hu Chunming
修正解码线程自然结束时解码器内存没...
|
265
266
267
268
269
|
if (m_post_decode_thread != 0)
{
pthread_join(m_post_decode_thread,0);
}
|
3c7e3e11
Hu Chunming
1.修改日志
|
270
271
|
decode_finished_cbk(m_userPtr);
|
48330793
Hu Chunming
修正解码线程自然结束时解码器内存没...
|
272
273
|
decode_finished();
|
d384f0e9
Hu Chunming
代码优化
|
274
|
av_log(nullptr, AV_LOG_INFO, "decode thread exited. \n");
|
aac5773f
hucm
功能基本完成,接口待打磨
|
275
276
|
}
|
48330793
Hu Chunming
修正解码线程自然结束时解码器内存没...
|
277
278
279
280
|
void FFNvDecoder::decode_finished()
{
if (avctx)
{
|
48330793
Hu Chunming
修正解码线程自然结束时解码器内存没...
|
281
282
283
284
285
286
287
288
289
|
avcodec_free_context(&avctx);
}
if (fmt_ctx)
{
avformat_close_input(&fmt_ctx);
}
m_bFinished = true;
|
bc52e542
Hu Chunming
添加关键帧解码功能
|
290
|
m_dec_keyframe = false;
|
48330793
Hu Chunming
修正解码线程自然结束时解码器内存没...
|
291
292
|
}
|
aac5773f
hucm
功能基本完成,接口待打磨
|
293
294
|
void FFNvDecoder::post_decode_thread()
{
|
3c7e3e11
Hu Chunming
1.修改日志
|
295
|
while (m_bRunning || mFrameQueue.length() > 0)
|
aac5773f
hucm
功能基本完成,接口待打磨
|
296
297
298
299
300
301
302
303
304
305
306
307
|
{
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();
}
|
3c7e3e11
Hu Chunming
1.修改日志
|
308
|
|
d384f0e9
Hu Chunming
代码优化
|
309
|
av_log(nullptr, AV_LOG_INFO, "post decode thread exited. \n");
|
aac5773f
hucm
功能基本完成,接口待打磨
|
310
311
312
313
314
|
}
void FFNvDecoder::close()
{
m_bRunning=false;
|
e96e6489
Hu Chunming
优化代码;添加isRunning函数
|
315
316
317
|
if(m_decode_thread != 0){
pthread_join(m_decode_thread,0);
}
|
bc52e542
Hu Chunming
添加关键帧解码功能
|
318
|
m_dec_keyframe = false;
|
aac5773f
hucm
功能基本完成,接口待打磨
|
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
|
}
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
修正解码线程自然结束时解码器内存没...
|
339
340
341
342
343
|
bool FFNvDecoder::isFinished()
{
return m_bFinished;
}
|
3c7e3e11
Hu Chunming
1.修改日志
|
344
345
346
347
|
bool FFNvDecoder::isPausing(){
return m_bPause;
}
|
aac5773f
hucm
功能基本完成,接口待打磨
|
348
349
|
bool FFNvDecoder::getResolution( int &width, int &height )
{
|
d384f0e9
Hu Chunming
代码优化
|
350
|
if (stream != nullptr && stream->codecpar != nullptr)
|
aac5773f
hucm
功能基本完成,接口待打磨
|
351
|
{
|
d384f0e9
Hu Chunming
代码优化
|
352
353
|
width = stream->codecpar->width;
height = stream->codecpar->height;
|
aac5773f
hucm
功能基本完成,接口待打磨
|
354
355
356
357
358
359
360
361
362
363
364
365
366
367
|
return true;
}
return false;
}
void FFNvDecoder::pause()
{
m_bPause = true;
}
void FFNvDecoder::resume()
{
m_bPause = false;
|
bc52e542
Hu Chunming
添加关键帧解码功能
|
368
369
370
371
372
|
}
void FFNvDecoder::setDecKeyframe(bool bKeyframe)
{
m_dec_keyframe = bKeyframe;
|
3c7e3e11
Hu Chunming
1.修改日志
|
373
374
375
376
377
378
379
380
|
}
int FFNvDecoder::getCachedQueueLength(){
return mFrameQueue.length();
}
FFImgInfo* FFNvDecoder::snapshot(const string& uri){
|
d384f0e9
Hu Chunming
代码优化
|
381
|
AVFormatContext* ifmt_ctx = nullptr;
|
3c7e3e11
Hu Chunming
1.修改日志
|
382
383
384
385
386
387
388
389
|
AVCodecContext* codec_ctx = nullptr;
AVCodec* codec = nullptr;
AVPacket* pkt = nullptr;
AVFrame *frame = nullptr;
AVFrame *pFrameRGB = nullptr;
int video_index = -1;
AVStream* st = nullptr;
SwsContext *img_convert_ctx = nullptr;
|
d384f0e9
Hu Chunming
代码优化
|
390
|
uint8_t *buffer = nullptr;
|
3c7e3e11
Hu Chunming
1.修改日志
|
391
392
393
|
int numBytes = 0;
FFImgInfo* imgInfo = nullptr;
|
d384f0e9
Hu Chunming
代码优化
|
394
395
|
|
3c7e3e11
Hu Chunming
1.修改日志
|
396
397
|
avformat_network_init();
|
d384f0e9
Hu Chunming
代码优化
|
398
399
400
401
402
403
404
|
// 打开输入视频文件
AVDictionary *options = nullptr;
av_dict_set( &options, "bufsize", "655360", 0 );
av_dict_set( &options, "rtsp_transport", "tcp", 0 );
// av_dict_set( &options, "listen_timeout", "30", 0 ); // 单位为s
av_dict_set( &options, "stimeout", "30000000", 0 ); // 单位为 百万分之一秒
|
3c7e3e11
Hu Chunming
1.修改日志
|
405
|
///打开输入的流
|
d384f0e9
Hu Chunming
代码优化
|
406
407
|
ifmt_ctx = avformat_alloc_context();
int ret = avformat_open_input(&ifmt_ctx, uri.c_str(), nullptr, &options);
|
3c7e3e11
Hu Chunming
1.修改日志
|
408
|
if (ret != 0){
|
d384f0e9
Hu Chunming
代码优化
|
409
|
av_log(nullptr, AV_LOG_ERROR, "Couldn't open input stream ! \n");
|
3c7e3e11
Hu Chunming
1.修改日志
|
410
411
412
413
|
goto end_flag ;
}
//查找流信息
|
d384f0e9
Hu Chunming
代码优化
|
414
415
|
if (avformat_find_stream_info(ifmt_ctx, nullptr) < 0){
av_log(nullptr, AV_LOG_ERROR, "Couldn't find stream information ! \n");
|
3c7e3e11
Hu Chunming
1.修改日志
|
416
417
418
419
|
goto end_flag ;
}
//找到视频流索引
|
d384f0e9
Hu Chunming
代码优化
|
420
|
video_index = av_find_best_stream(ifmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, nullptr, 0);
|
3c7e3e11
Hu Chunming
1.修改日志
|
421
422
423
424
425
426
|
st = ifmt_ctx->streams[video_index];
//找到解码器
codec = avcodec_find_decoder(st->codecpar->codec_id);
if (!codec){
|
d384f0e9
Hu Chunming
代码优化
|
427
|
av_log(nullptr, AV_LOG_ERROR, "Codec not found ! \n");
|
3c7e3e11
Hu Chunming
1.修改日志
|
428
429
430
431
432
433
434
435
436
437
438
439
|
goto end_flag ;
}
//申请AVCodecContext
codec_ctx = avcodec_alloc_context3(codec);
if (!codec_ctx){
goto end_flag ;
}
avcodec_parameters_to_context(codec_ctx, ifmt_ctx->streams[video_index]->codecpar);
//打开解码器
|
d384f0e9
Hu Chunming
代码优化
|
440
|
if ((ret = avcodec_open2(codec_ctx, codec, nullptr) < 0)){
|
3c7e3e11
Hu Chunming
1.修改日志
|
441
442
443
444
445
446
447
448
449
450
451
|
goto end_flag ;
}
// 计算解码后原始数据所需缓冲区大小,并分配内存空间 Determine required buffer size and allocate buffer
numBytes = av_image_get_buffer_size(AV_PIX_FMT_RGB24, codec_ctx->width, codec_ctx->height, 1);
buffer = (uint8_t *)av_malloc(numBytes * sizeof(uint8_t));
pFrameRGB = av_frame_alloc();
av_image_fill_arrays(pFrameRGB->data, pFrameRGB->linesize, buffer, AV_PIX_FMT_BGR24, codec_ctx->width, codec_ctx->height, 1);
img_convert_ctx = sws_getContext(codec_ctx->width, codec_ctx->height,codec_ctx->pix_fmt, codec_ctx->width, codec_ctx->height, AV_PIX_FMT_BGR24,
|
d384f0e9
Hu Chunming
代码优化
|
452
|
SWS_BICUBIC, nullptr, nullptr, nullptr);
|
3c7e3e11
Hu Chunming
1.修改日志
|
453
454
455
456
457
458
459
460
461
|
pkt = av_packet_alloc();
frame = av_frame_alloc();
while (av_read_frame(ifmt_ctx, pkt) >= 0){
if (pkt->stream_index == video_index){
int ret = avcodec_send_packet(codec_ctx, pkt);
if (ret >= 0){
ret = avcodec_receive_frame(codec_ctx, frame);
if ((ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) || ret < 0){
|
d384f0e9
Hu Chunming
代码优化
|
462
463
|
av_log(nullptr, AV_LOG_ERROR, "Failed to receive frame: %d \n", ret);
av_packet_unref(pkt);
|
3c7e3e11
Hu Chunming
1.修改日志
|
464
465
466
467
468
469
470
471
472
|
continue;
}
sws_scale(img_convert_ctx, (const unsigned char* const*)frame->data, frame->linesize, 0, codec_ctx->height, pFrameRGB->data, pFrameRGB->linesize);
imgInfo = new FFImgInfo();
imgInfo->pData = buffer;
imgInfo->height = codec_ctx->height;
imgInfo->width = codec_ctx->width;
|
3c7e3e11
Hu Chunming
1.修改日志
|
473
474
475
|
break;
}
}
|
d384f0e9
Hu Chunming
代码优化
|
476
477
|
av_packet_unref(pkt);
|
3c7e3e11
Hu Chunming
1.修改日志
|
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
|
}
end_flag:
if (codec_ctx != nullptr){
avcodec_close(codec_ctx);
avcodec_free_context(&codec_ctx);
}
if (ifmt_ctx != nullptr){
avformat_close_input(&ifmt_ctx);
}
if (frame != nullptr){
av_frame_free(&frame);
}
if (pFrameRGB != nullptr){
av_frame_free(&pFrameRGB);
}
if (pkt != nullptr){
av_packet_free(&pkt);
}
return imgInfo;
}
void FFNvDecoder::releaseFFImgInfo(FFImgInfo* info){
if(nullptr != info){
if(info->pData != nullptr){
av_free(info->pData);
info->pData = nullptr;
}
delete info;
info = nullptr;
}
|
d384f0e9
Hu Chunming
代码优化
|
514
|
}
|