Blame view

src/FFNvDecoder.cpp 11.5 KB
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){
6fc86385   ming   代码优化
236
  				av_log(nullptr, AV_LOG_ERROR, "%s - Failed to send pkt: %d \n",name,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){
6fc86385   ming   代码优化
242
  				av_log(nullptr, AV_LOG_ERROR, "%s - Failed to receive frame: %d \n",name,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();
  
6fc86385   ming   代码优化
274
  	av_log(nullptr, AV_LOG_INFO, "%s - decode thread exited. \n",name);
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
  }