Blame view

src/decoder/dvpp/DvppSnapshot.cpp 23.7 KB
4061a3c3   Hu Chunming   更换decoder
1
  #include "DvppSnapshot.h"
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
2
3
  #include "DvppSourceManager.h"
  
4061a3c3   Hu Chunming   更换decoder
4
5
  #include "VpcUtils.h"
  
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
6
  
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
7
8
9
10
11
12
13
14
  #define CHECK_NOT_RETURN(ret, message)    \
              if(ret != 0) {LOG_ERROR("[{}]- {}", m_dec_name, message);}
  #define CHECK_AND_RETURN_NOVALUE(ret, message)    \
              if(ret != 0) {LOG_ERROR("[{}]- {}", m_dec_name, message); return;}
  #define CHECK_AND_BREAK(ret, message)    \
              if(ret != 0) {LOG_ERROR("[{}]- {}", m_dec_name, message); break;}
  
  
4061a3c3   Hu Chunming   更换decoder
15
16
17
  
  constexpr int MAX_QUEUE_LENGTH = 3;
  
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
18
19
20
21
22
  struct Vdec_CallBack_UserData {
      uint64_t frameId;
      uint64_t frame_nb;
      long startTime;
      long sendTime;
4061a3c3   Hu Chunming   更换decoder
23
  	DvppSnapshot* self;
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
24
25
26
27
28
29
30
  
      Vdec_CallBack_UserData() {
          frameId = 0;
          frame_nb = 0;
      }
  };
  
4061a3c3   Hu Chunming   更换decoder
31
32
33
34
35
36
37
  
  static long get_cur_time_ms() {
      chrono::time_point<chrono::system_clock, chrono::milliseconds> tpMicro
          = chrono::time_point_cast<chrono::milliseconds>(chrono::system_clock::now());
      return tpMicro.time_since_epoch().count();
  }
  
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
38
39
  static void *ReportThd(void *arg)
  {
4061a3c3   Hu Chunming   更换decoder
40
      DvppSnapshot *self = (DvppSnapshot *)arg;
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
41
42
43
44
45
46
47
48
49
50
  	if(nullptr != self){
  		self->doProcessReport();
  	}
      return (void *)0;
  }
  
  static void VdecCallback(acldvppStreamDesc *input, acldvppPicDesc *output, void *pUserData)
  {
  	Vdec_CallBack_UserData *userData = (Vdec_CallBack_UserData *) pUserData;
      if(nullptr != userData){
4061a3c3   Hu Chunming   更换decoder
51
          DvppSnapshot* self = userData->self;
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
52
53
54
55
56
57
58
59
          if(self != nullptr){
              self->doVdppVdecCallBack(input, output, userData);
          }
          delete userData;
  	    userData = nullptr;
      }
  }
  
4061a3c3   Hu Chunming   更换decoder
60
  DvppSnapshot::DvppSnapshot(){
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
61
  
4061a3c3   Hu Chunming   更换decoder
62
63
64
65
66
67
68
69
70
71
72
73
74
75
      fmt_ctx = nullptr;
  	m_bRunning = false;
  
      video_index = -1;
      pix_fmt = AV_PIX_FMT_NONE;
      m_dec_name = "";
  
  	m_bReal = true;
  
  	m_bFinished = false;
  	m_fps = 0.0;
  
      std::queue<DvppDataMemory*>().swap(m_decoded_data_queue);
  }
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
76
  
4061a3c3   Hu Chunming   更换decoder
77
78
  DvppSnapshot::~DvppSnapshot(){
      LOG_DEBUG("[{}]- ~DvppSnapshot() in_count:{}  out_count:{}", m_dec_name, m_in_count, m_out_count);
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
79
80
  }
  
4061a3c3   Hu Chunming   更换decoder
81
  bool DvppSnapshot::init(FFDecConfig cfg){
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
82
83
84
  
      m_dec_name = cfg.dec_name;
  
4061a3c3   Hu Chunming   更换decoder
85
86
87
88
89
90
91
92
93
94
95
96
97
      m_cfg = cfg;
  
      AVCodecContext* avctx = init_FFmpeg(cfg);
      if(avctx == nullptr){
          return false;
      }
  
      do
      {
          bool bRet = init_vdpp(cfg, avctx);
          if(!bRet){
              break;
          }
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
98
  
4061a3c3   Hu Chunming   更换decoder
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
          m_bFinished = false;
  
          return true;
      } while (0);
  
      release_ffmpeg();
      
      return false;
  }
  
  AVCodecContext* DvppSnapshot::init_FFmpeg(FFDecConfig config){
  
      const char* input_file = config.uri.c_str();
  
  	// 打开输入视频文件
  	AVDictionary *options = nullptr;
  	av_dict_set( &options, "bufsize", "655360", 0 );
  	av_dict_set( &options, "rtsp_transport", "tcp", 0 );
  	av_dict_set( &options, "stimeout", "30000000", 0 ); // 单位为 百万分之一秒
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
118
119
  
      do{
4061a3c3   Hu Chunming   更换decoder
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
          fmt_ctx = avformat_alloc_context();
          if (avformat_open_input(&fmt_ctx, input_file, nullptr, &options) != 0) {
              LOG_ERROR("[{}]- Cannot open input file: {}", m_dec_name, input_file);
              break;
          }
          av_dump_format(fmt_ctx, 0, input_file, 0);
  
          FILE* infile = fopen(input_file, "r");
          if(nullptr != infile) {
              // 可以作为本地文件打开,那必然是文件
              m_bReal = false;
              fclose(infile);
              infile = nullptr;
          } else {
              // http://xxxx/xxx.mp4   也与文件同
              if (fmt_ctx->iformat && fmt_ctx->iformat->extensions) {
                  m_bReal = false;
              } else {
                  m_bReal = true;
              }
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
140
141
          }
  
4061a3c3   Hu Chunming   更换decoder
142
143
144
145
          // 查找流信息
          if (avformat_find_stream_info(fmt_ctx, nullptr) < 0) {
              LOG_ERROR("[{}]- Cannot find input stream information!", m_dec_name);
              break;
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
146
147
          }
  
4061a3c3   Hu Chunming   更换decoder
148
149
150
151
152
153
154
          // 查找视频流信息
          AVCodec *decoder = nullptr;
          video_index = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, &decoder, 0);
          if (video_index < 0) {
              LOG_ERROR("[{}]- Cannot find a video stream in the input file!", m_dec_name);
              break;
          }
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
155
  
4061a3c3   Hu Chunming   更换decoder
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
          avctx = avcodec_alloc_context3(decoder);
          if(avctx == nullptr){
              LOG_ERROR("[{}]- alloc AVCodecContext failed!", m_dec_name);
              break;
          }
  	
  		// 得到视频流对象
  		AVStream* stream = fmt_ctx->streams[video_index];
  		AVCodecParameters *codecpar = stream->codecpar;
  		if (avcodec_parameters_to_context(avctx, codecpar) < 0)
  			break;
  
  		const AVBitStreamFilter * filter = nullptr;
  		if(codecpar->codec_id == AV_CODEC_ID_H264){
  			filter = av_bsf_get_by_name("h264_mp4toannexb");
  		}else if(codecpar->codec_id == AV_CODEC_ID_HEVC){
  			filter = av_bsf_get_by_name("hevc_mp4toannexb");
  		}else {
              LOG_ERROR("[{}]- codec_id is not supported!", m_dec_name);
  			break;
  		}
  
          int enType = getVdecType(codecpar->codec_id, codecpar->profile);
          if(-1 == enType) {
              break;
          }
          m_enType = static_cast<acldvppStreamFormat>(enType);
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
183
  
4061a3c3   Hu Chunming   更换decoder
184
185
186
187
188
189
190
  		int ret = av_bsf_alloc(filter, &h264bsfc);
  		if (ret < 0){
  			break;
  		}
  		
  		avcodec_parameters_copy(h264bsfc->par_in, codecpar);
  		av_bsf_init(h264bsfc);
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
191
  
4061a3c3   Hu Chunming   更换decoder
192
193
194
  		frame_width = codecpar->width;
  		frame_height = codecpar->height;
  		pix_fmt = (AVPixelFormat)codecpar->format;
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
195
  
4061a3c3   Hu Chunming   更换decoder
196
197
          m_bResize = config.resize;
          calcOutResolution(frame_width, frame_height);
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
198
  
4061a3c3   Hu Chunming   更换decoder
199
200
201
202
203
          if (stream->avg_frame_rate.den) {
              m_fps = av_q2d(stream ->avg_frame_rate);
          } else {
              m_fps = 0.0;
          }
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
204
  
4061a3c3   Hu Chunming   更换decoder
205
          LOG_INFO("[{}]- init ffmpeg success! input:{} src:({}, {}) out:({}, {}) fps:{} ", m_dec_name, input_file, frame_width, frame_height, out_frame_width, out_frame_height, m_fps);
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
206
  
4061a3c3   Hu Chunming   更换decoder
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
  		return avctx;
  	}while(0);
  
      release_ffmpeg();
  
      LOG_ERROR("[{}]- init ffmpeg failed ! input:{} ", m_dec_name, input_file);
  
      return nullptr;
  }
  
  void DvppSnapshot::calcOutResolution(int width, int height) {
      if(m_bResize) {
          float srcRatio = width / (float)height;
          float stdRatio = 1920.0 / 1080.0f ;
          int outWidth = 1920;
          int outHeight = 1080;
          if (srcRatio > stdRatio) {
              outHeight = static_cast<int>(outWidth * (float)height / width) ;
              if (outHeight % 2 == 1) {
                  outHeight += 1;
              }
          } else if (srcRatio < stdRatio) {
              outWidth = static_cast<int>(outHeight * (float)width / height) ;
              if (outWidth % 2 == 1) {
                  outWidth += 1;
              }
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
233
          }
4061a3c3   Hu Chunming   更换decoder
234
235
236
237
238
239
  
          out_frame_width = outWidth;
          out_frame_height = outHeight;
      } else {
          out_frame_width = width;
          out_frame_height = height;
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
240
241
      }
      
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
242
243
  }
  
4061a3c3   Hu Chunming   更换decoder
244
  int DvppSnapshot::getVdecType(int videoType, int profile)
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
245
246
247
248
  {
      int streamFormat = H264_MAIN_LEVEL;
  
      // VDEC only support H265 main level264 baseline levelmain levelhigh level
4061a3c3   Hu Chunming   更换decoder
249
      if (videoType == AV_CODEC_ID_HEVC) {
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
250
          streamFormat = H265_MAIN_LEVEL;
4061a3c3   Hu Chunming   更换decoder
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
      } else if (videoType == AV_CODEC_ID_H264) {
          switch (profile) {
              case FF_PROFILE_H264_BASELINE:
                  streamFormat = H264_BASELINE_LEVEL;
                  break;
              case FF_PROFILE_H264_MAIN:
                  streamFormat = H264_MAIN_LEVEL;
                  break;
              case FF_PROFILE_H264_HIGH:
              case FF_PROFILE_H264_HIGH_10:
              case FF_PROFILE_H264_HIGH_10_INTRA:
              case FF_PROFILE_H264_MULTIVIEW_HIGH:
              case FF_PROFILE_H264_HIGH_422:
              case FF_PROFILE_H264_HIGH_422_INTRA:
              case FF_PROFILE_H264_STEREO_HIGH:
              case FF_PROFILE_H264_HIGH_444:
              case FF_PROFILE_H264_HIGH_444_PREDICTIVE:
              case FF_PROFILE_H264_HIGH_444_INTRA:
                  streamFormat = H264_HIGH_LEVEL;
                  break;
              default:
                  LOG_INFO("Not support h264 profile {}, use as mp", profile);
                  streamFormat = H264_MAIN_LEVEL;
                  break;
          }
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
276
277
      } else {
          streamFormat = -1;
4061a3c3   Hu Chunming   更换decoder
278
          LOG_ERROR("Not support stream, type {},  profile {}", videoType, profile);
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
279
280
281
282
283
      }
  
      return streamFormat;
  }
  
4061a3c3   Hu Chunming   更换decoder
284
   bool DvppSnapshot::init_vdpp(FFDecConfig cfg, AVCodecContext* avctx) {
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
285
  
4061a3c3   Hu Chunming   更换decoder
286
      LOG_INFO("[{}]- Init device start...", m_dec_name);
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
287
  
4061a3c3   Hu Chunming   更换decoder
288
      m_dvpp_deviceId = atoi(cfg.gpuid.c_str());
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
289
  
4061a3c3   Hu Chunming   更换decoder
290
      VpcUtils::getInstance(m_dvpp_deviceId); // 初始化工具类
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
291
  
4061a3c3   Hu Chunming   更换decoder
292
293
294
295
296
297
      do{
          aclError ret = aclrtSetDevice(m_dvpp_deviceId);
          if(ret != ACL_ERROR_NONE){
              LOG_ERROR("[{}]-aclrtSetDevice failed !", m_dec_name);
              break;
          }
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
298
  
4061a3c3   Hu Chunming   更换decoder
299
300
301
302
303
          ret = aclrtCreateContext(&m_context, m_dvpp_deviceId);
          if (ret != ACL_ERROR_NONE) {
              LOG_ERROR("[{}]-aclrtCreateContext failed !", m_dec_name);
              break;
          }
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
304
  
4061a3c3   Hu Chunming   更换decoder
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
          // DvppSourceManager 创建时包含 aclInit,析构时包含 aclFinalize
          DvppSourceManager* pSrcMgr = DvppSourceManager::getInstance();
          m_dvpp_channel = pSrcMgr->getChannel(m_dvpp_deviceId);
          if(m_dvpp_channel < 0){
              LOG_ERROR("[{}]-该设备channel已经用完了!", m_dec_name);
              break;
          }
  
          m_vdec_out_size = frame_width * frame_height * 3;
  
          LOG_INFO("[{}]- init vdpp success! device:{} channel:{}", m_dec_name, m_dvpp_deviceId, m_dvpp_channel);
          return true;
      }while(0);
  
      release_dvpp();
  
      return false;
  }
  
  void DvppSnapshot::release_ffmpeg() {
  
  	if(h264bsfc){
  		av_bsf_free(&h264bsfc);
  		h264bsfc = nullptr;
  	}
      if(avctx){
          avcodec_free_context(&avctx);
          avctx = nullptr;
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
333
      }
4061a3c3   Hu Chunming   更换decoder
334
335
336
337
      if (fmt_ctx){
  		avformat_close_input(&fmt_ctx);
  		fmt_ctx = nullptr;
  	}
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
338
  
4061a3c3   Hu Chunming   更换decoder
339
340
      LOG_DEBUG("[{}]- release_ffmpeg", m_dec_name);
  }
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
341
  
4061a3c3   Hu Chunming   更换decoder
342
  DvppDataMemory* DvppSnapshot::snapshot() {
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
343
  
4061a3c3   Hu Chunming   更换decoder
344
  	int ret = -1;
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
345
  
4061a3c3   Hu Chunming   更换decoder
346
347
348
349
350
351
352
      m_bExitReportThd = false;
  	pthread_t report_thread;
  	ret = pthread_create(&report_thread, nullptr, ReportThd, (void *)this);
  	if(ret != 0){
          LOG_ERROR("[{}]- pthread_create failed", m_dec_name);
  		return nullptr;
  	}
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
353
  
4061a3c3   Hu Chunming   更换decoder
354
355
356
      aclrtContext ctx = nullptr;
      aclrtStream stream = nullptr;
      aclvdecChannelDesc *vdecChannelDesc = nullptr;
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
357
  
4061a3c3   Hu Chunming   更换decoder
358
359
360
361
362
363
364
365
366
367
      m_bRunning = true;
  
      do {
          CHECK_AND_BREAK(aclrtSetDevice(m_dvpp_deviceId), "aclrtSetDevice failed");
          CHECK_AND_BREAK(aclrtCreateContext(&ctx, m_dvpp_deviceId), "aclrtCreateContext failed");
          CHECK_AND_BREAK(aclrtCreateStream(&stream), "aclrtCreateStream failed");
  
          vdecChannelDesc = aclvdecCreateChannelDesc();
          if (vdecChannelDesc == nullptr) { 
              LOG_ERROR("[{}]- aclvdecCreateChannelDesc failed", m_dec_name);
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
368
369
370
              break;
          }
  
4061a3c3   Hu Chunming   更换decoder
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
          // 创建 channel dec结构体
          // 通道IDdvpp层面为0~31
          CHECK_AND_BREAK(aclvdecSetChannelDescChannelId(vdecChannelDesc, m_dvpp_channel), "aclvdecSetChannelDescChannelId failed");
          CHECK_AND_BREAK(aclvdecSetChannelDescThreadId(vdecChannelDesc, report_thread), "aclvdecSetChannelDescThreadId failed");
          CHECK_AND_BREAK(aclvdecSetChannelDescCallback(vdecChannelDesc, VdecCallback), "aclvdecSetChannelDescCallback failed");
          CHECK_AND_BREAK(aclvdecSetChannelDescEnType(vdecChannelDesc, m_enType), "aclvdecSetChannelDescEnType failed");
          // CHECK_AND_BREAK(aclvdecSetChannelDescOutPicFormat(vdecChannelDesc, PIXEL_FORMAT_YUV_SEMIPLANAR_420), "aclvdecSetChannelDescOutPicFormat failed"); 
          CHECK_AND_BREAK(aclvdecSetChannelDescOutPicFormat(vdecChannelDesc, PIXEL_FORMAT_BGR_888), "aclvdecSetChannelDescOutPicFormat failed"); 
          CHECK_AND_BREAK(aclvdecCreateChannel(vdecChannelDesc), "aclvdecCreateChannel failed");
  
          AVPacket* pkt = av_packet_alloc();
          av_init_packet( pkt );
          unsigned long long frame_nb = 0;
          while (m_bRunning){
  
              m_decoded_data_queue_mtx.lock();
              if(m_decoded_data_queue.size() > 1){
                  m_decoded_data_queue_mtx.unlock();
                  std::this_thread::sleep_for(std::chrono::milliseconds(5));
                  break;
              }
              m_decoded_data_queue_mtx.unlock();
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
393
  
4061a3c3   Hu Chunming   更换decoder
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
              int result = av_read_frame(fmt_ctx, pkt);
              if (result == AVERROR_EOF || result < 0){
                  av_packet_unref(pkt);
                  LOG_WARN("[{}]- Failed to read frame!", m_dec_name);
                  break;
              }
  
              if (m_bReal && m_DvppCacheCounter.load() > 20){
                  // 解码器解码不过来。实时流在此处的处理会导致花屏,这是由于解码器性能问题导致,无法避免
                  // 实时流在这里处理是为了避免长时间不读取数据导致数据中断
                  std::this_thread::sleep_for(std::chrono::milliseconds(10));
                  continue;
              }
  
              if (video_index == pkt->stream_index){
  
                  ret = av_bsf_send_packet(h264bsfc, pkt);
                  if(ret < 0) {
                      LOG_ERROR("[{}]- av_bsf_send_packet error!", m_dec_name);
                      av_packet_unref(pkt);
                      continue;
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
415
416
                  }
  
4061a3c3   Hu Chunming   更换decoder
417
418
419
420
421
422
423
424
425
426
                  int nSended = -1;
                  while ((ret = av_bsf_receive_packet(h264bsfc, pkt)) == 0) {
  
                      if(!m_bRunning){
                          break;
                      }
  
                      nSended = sendPkt(vdecChannelDesc, pkt, frame_nb);
  
                      frame_nb++;
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
427
  
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
428
                  }
4061a3c3   Hu Chunming   更换decoder
429
430
431
432
433
434
435
  
                  if(nSended < 0) {
                      // 执行出错,强行结束整个任务
                      m_bRunning=false;
                      break;
                  }
              } 
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
436
              
4061a3c3   Hu Chunming   更换decoder
437
438
439
              // 音频等其他分量的情形
              av_packet_unref(pkt);
          }
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
440
  
4061a3c3   Hu Chunming   更换decoder
441
442
443
444
445
          av_packet_free(&pkt);
          pkt = nullptr;
  
          if (vdecChannelDesc) {
              sendVdecEos(vdecChannelDesc);
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
446
          }
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
447
  
4061a3c3   Hu Chunming   更换decoder
448
449
450
      } while (0);
  
      DvppDataMemory* snapshot_mem = nullptr;
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
451
  
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
452
      if (m_decoded_data_queue.size() > 0) {
4061a3c3   Hu Chunming   更换decoder
453
454
          auto mem = m_decoded_data_queue.front();
          snapshot_mem = new DvppDataMemory(mem);
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
455
      }
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
456
  
4061a3c3   Hu Chunming   更换decoder
457
458
459
460
461
      if (vdecChannelDesc) {
          CHECK_NOT_RETURN(aclvdecDestroyChannel(vdecChannelDesc), "aclvdecDestroyChannel failed");
          CHECK_NOT_RETURN(aclvdecDestroyChannelDesc(vdecChannelDesc), "aclvdecDestroyChannelDesc failed");
          vdecChannelDesc = nullptr;
      }
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
462
  
4061a3c3   Hu Chunming   更换decoder
463
464
465
466
467
468
469
470
471
472
473
      m_bRunning=false;
  
      m_bExitReportThd = true;
  	CHECK_NOT_RETURN(pthread_join(report_thread, nullptr), "report_thread join failed");
  
      m_decoded_data_queue_mtx.lock();
      while (!m_decoded_data_queue.empty()) {
          DvppDataMemory* memPtr = m_decoded_data_queue.front();
          m_decoded_data_queue.pop();
          delete memPtr;
          memPtr = nullptr;
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
474
      }
4061a3c3   Hu Chunming   更换decoder
475
476
477
478
      m_decoded_data_queue_mtx.unlock();
  
      if(stream){
          CHECK_NOT_RETURN(aclrtDestroyStream(stream), "aclrtDestroyStream failed");
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
479
480
      }
  
4061a3c3   Hu Chunming   更换decoder
481
482
      if (ctx){
          CHECK_NOT_RETURN(aclrtDestroyContext(ctx), "aclrtDestroyContext failed");
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
483
      }
4061a3c3   Hu Chunming   更换decoder
484
485
486
      
      release_ffmpeg();
      release_dvpp();
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
487
  
4061a3c3   Hu Chunming   更换decoder
488
489
490
491
492
      m_bFinished = true;
  
      LOG_INFO("[{}]- snapshot finished.", m_dec_name);
  
      return snapshot_mem;
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
493
494
  }
  
4061a3c3   Hu Chunming   更换decoder
495
  int DvppSnapshot::sendPkt(aclvdecChannelDesc *vdecChannelDesc, AVPacket* pkt, unsigned long long frame_nb){
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
  
      void *vdecInputbuf = nullptr;
      void *vdecOutputBuf = nullptr;
      acldvppStreamDesc *input_stream_desc = nullptr;
      acldvppPicDesc *output_pic_desc = nullptr;
      do{
          int ret = acldvppMalloc((void **)&vdecInputbuf, pkt->size);
          if(ACL_ERROR_NONE != ret){
              LOG_ERROR("[{}]- acldvppMalloc failed!, ret:{}", m_dec_name, ret);
              break;
          }
  
           ret = aclrtMemcpy(vdecInputbuf, pkt->size, pkt->data, pkt->size, ACL_MEMCPY_HOST_TO_DEVICE);
          if(ACL_ERROR_NONE != ret){
              LOG_ERROR("[{}]- aclrtMemcpy failed", m_dec_name);
              break;
          }
  
4061a3c3   Hu Chunming   更换decoder
514
          ret = acldvppMalloc((void **)&vdecOutputBuf, m_vdec_out_size);
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
          if(ret != ACL_ERROR_NONE){
              LOG_ERROR("[{}]- acldvppMalloc failed", m_dec_name);
              break;
          }
  
          input_stream_desc = acldvppCreateStreamDesc();
          if (input_stream_desc == nullptr) { 
              LOG_ERROR("[{}]- acldvppCreateStreamDesc failed", m_dec_name);
              break;
          }
          output_pic_desc = acldvppCreatePicDesc();
          if (output_pic_desc == nullptr) { 
              LOG_ERROR("[{}]- acldvppCreatePicDesc failed", m_dec_name);
              break;
          }
          CHECK_AND_BREAK(acldvppSetStreamDescData(input_stream_desc, vdecInputbuf), "acldvppSetStreamDescData failed");
          CHECK_AND_BREAK(acldvppSetStreamDescSize(input_stream_desc, pkt->size), "acldvppSetStreamDescSize failed");
          CHECK_AND_BREAK(acldvppSetPicDescData(output_pic_desc, vdecOutputBuf), "acldvppSetPicDescData failed");
4061a3c3   Hu Chunming   更换decoder
533
          CHECK_AND_BREAK(acldvppSetPicDescSize(output_pic_desc, m_vdec_out_size), "acldvppSetPicDescSize failed");
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
          
          Vdec_CallBack_UserData *user_data = NULL;
          user_data = new Vdec_CallBack_UserData;
          user_data->frameId = frame_nb;
          user_data->frame_nb = frame_nb;
          // user_data->startTime = startTime;
          user_data->sendTime = UtilTools::get_cur_time_ms();
          user_data->self = this;
  
          m_in_count++;
  
          // 内部缓存计数加1
          m_DvppCacheCounter++;
          ret = aclvdecSendFrame(vdecChannelDesc, input_stream_desc, output_pic_desc, nullptr, reinterpret_cast<void *>(user_data));
          if(ret != ACL_ERROR_NONE){
              LOG_ERROR("[{}]- aclvdecSendFrame failed", m_dec_name);
              delete user_data;
              user_data = nullptr;
              return -2;
          }
  
          return 0;
      }while (0);
  
      if (vdecInputbuf){
          acldvppFree(vdecInputbuf);
          vdecInputbuf = nullptr;
      }
  
      // 报错情形
      if(input_stream_desc){
          CHECK_NOT_RETURN(acldvppDestroyStreamDesc(input_stream_desc), "acldvppDestroyStreamDesc failed");
      }
  
      if (vdecOutputBuf){
          acldvppFree(vdecOutputBuf);
  	    vdecOutputBuf = nullptr;
      }
  
      if(output_pic_desc){
          CHECK_NOT_RETURN(acldvppDestroyPicDesc(output_pic_desc), "acldvppDestroyPicDesc failed");
      }
  
      return -1;
  }
  
4061a3c3   Hu Chunming   更换decoder
580
  void DvppSnapshot::doProcessReport(){
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
581
  
4061a3c3   Hu Chunming   更换decoder
582
      aclError ret = aclrtSetDevice(m_dvpp_deviceId);
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
583
      if(ret != ACL_ERROR_NONE){
4061a3c3   Hu Chunming   更换decoder
584
585
586
          // cout << "aclrtSetDevice failed" << endl;
          LOG_ERROR("aclrtSetDevice failed !");
          return ;
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
587
588
      }
  
4061a3c3   Hu Chunming   更换decoder
589
590
591
592
593
594
      aclrtContext ctx;
      ret = aclrtCreateContext(&ctx, m_dvpp_deviceId);
      if (ret != ACL_ERROR_NONE) {
          // cout << "aclrtCreateContext failed " << endl;
          LOG_ERROR("aclrtCreateContext failed !");
          return ;
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
595
596
      }
  
4061a3c3   Hu Chunming   更换decoder
597
598
      while (!m_bExitReportThd) {
          aclrtProcessReport(1000);
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
599
600
      }
  
4061a3c3   Hu Chunming   更换decoder
601
602
603
604
605
      ret = aclrtDestroyContext(ctx);
      if(ret != ACL_ERROR_NONE){
          LOG_ERROR("aclrtDestroyContext failed !");
      }
      LOG_INFO("doProcessReport exit.");
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
606
607
  }
  
4061a3c3   Hu Chunming   更换decoder
608
609
610
611
  void DvppSnapshot::doVdppVdecCallBack(acldvppStreamDesc *input, acldvppPicDesc *output, void *pUserData){
  
      // 内部缓存计数减1
      m_DvppCacheCounter--;
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
612
  
4061a3c3   Hu Chunming   更换decoder
613
614
      if(nullptr == pUserData){
          return;
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
615
616
      }
  
4061a3c3   Hu Chunming   更换decoder
617
618
      Vdec_CallBack_UserData *userData = (Vdec_CallBack_UserData *) pUserData;
      uint64_t frame_nb = userData->frame_nb;
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
619
  
4061a3c3   Hu Chunming   更换decoder
620
      m_out_count++;
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
621
  
4061a3c3   Hu Chunming   更换decoder
622
      CHECK_AND_RETURN_NOVALUE(aclrtSetCurrentContext(m_context), "aclrtSetCurrentContext failed");
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
623
  
4061a3c3   Hu Chunming   更换decoder
624
625
626
      void *inputDataDev = acldvppGetStreamDescData(input);
      acldvppFree(inputDataDev);
      inputDataDev = nullptr;
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
627
  
4061a3c3   Hu Chunming   更换decoder
628
629
630
631
632
633
      void *outputDataDev = acldvppGetPicDescData(output);
      uint32_t outputSize = acldvppGetPicDescSize(output);
      uint32_t width = acldvppGetPicDescWidth(output);
      uint32_t width_stride = acldvppGetPicDescWidthStride(output);
      uint32_t height = acldvppGetPicDescHeight(output);
      uint32_t height_stride = acldvppGetPicDescHeightStride(output);
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
634
  
4061a3c3   Hu Chunming   更换decoder
635
636
637
638
639
640
641
642
      bool bCached = false;
      do{
          int ret = acldvppGetPicDescRetCode(output);
          if(ret != ACL_ERROR_NONE){
              LOG_ERROR("[{}]- decode result error, frame_nb:{}, retCode:{} ", m_dec_name, frame_nb, ret);
              acldvppFree(outputDataDev);
              outputDataDev = nullptr;
              break;
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
643
          }
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
644
  
4061a3c3   Hu Chunming   更换decoder
645
          if(width > 0 && height > 0 && outputSize > 0){
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
646
  
4061a3c3   Hu Chunming   更换decoder
647
648
649
650
651
              // 限制队列的最大长度为20
              m_decoded_data_queue_mtx.lock();
              if(m_decoded_data_queue.size() >= 20){
                  m_decoded_data_queue_mtx.unlock();
                  break;
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
652
              }
4061a3c3   Hu Chunming   更换decoder
653
              m_decoded_data_queue_mtx.unlock();
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
654
  
4061a3c3   Hu Chunming   更换decoder
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
              // 换成解码后数据, 这里这样做的是为了保证解码一直持续进行,避免后续操作阻碍文件读取和解码从而导致花屏
               DvppDataMemory* mem = nullptr;
              if (m_bResize && (width > 1920 || height > 1080)) {
                  float srcRatio = width / (float)height;
                  float stdRatio = 1920.0 / 1080.0f ;
                  int outWidth = 1920;
                  int outHeight = 1080;
                  if (srcRatio > stdRatio) {
                      outHeight = static_cast<int>(outWidth * (float)height / width) ;
                      if (outHeight % 2 == 1)
                      {
                          outHeight += 1;
                      }
                  } else if (srcRatio < stdRatio) {
                      outWidth = static_cast<int>(outHeight * (float)width / height) ;
                      if (outWidth % 2 == 1)
                      {
                          outWidth += 1;
                      }
                  }
                  
                  VpcUtils* pUtils = VpcUtils::getInstance(m_dvpp_deviceId);
                  mem = pUtils->resize(output, outWidth, outHeight);
                  if (mem)  {
                      acldvppFree(outputDataDev);
                      outputDataDev = nullptr;
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
681
  
4061a3c3   Hu Chunming   更换decoder
682
683
684
685
686
                      mem->setDeviceId(to_string(m_dvpp_deviceId));
                      mem->setId(m_dec_name);
                      mem->setFrameNb(frame_nb);
                  }
              } else {
881ac79d   Hu Chunming   代码调通,结果正常输出
687
                  mem = new DvppDataMemory(width, width_stride, height, height_stride, outputSize, m_dec_name, to_string(m_dvpp_deviceId), false, frame_nb, (unsigned char *)outputDataDev);
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
688
689
              }
              
4061a3c3   Hu Chunming   更换decoder
690
691
692
693
694
              if(mem != nullptr){
                  m_decoded_data_queue.push(mem);
                  bCached = true;
              } else {
                  LOG_WARN("[{}]- decode result warning, width:{} width_stride:{} height:{} height_stride:{} size:{}", m_dec_name, width, width_stride, height, height_stride, outputSize);
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
695
              }
4061a3c3   Hu Chunming   更换decoder
696
697
698
          } 
          
      }while(0);
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
699
  
4061a3c3   Hu Chunming   更换decoder
700
701
702
703
      if(!bCached) {
          acldvppFree(outputDataDev);
          outputDataDev = nullptr;
      }
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
704
  
4061a3c3   Hu Chunming   更换decoder
705
706
707
  	CHECK_AND_RETURN_NOVALUE(acldvppDestroyStreamDesc(input), "acldvppDestroyStreamDesc failed");
  	CHECK_AND_RETURN_NOVALUE(acldvppDestroyPicDesc(output), "acldvppDestroyPicDesc failed");
  }
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
708
  
4061a3c3   Hu Chunming   更换decoder
709
710
711
712
713
714
  bool DvppSnapshot::sendVdecEos(aclvdecChannelDesc *vdecChannelDesc) {
      // create stream desc
      acldvppStreamDesc *streamInputDesc = acldvppCreateStreamDesc();
      if (streamInputDesc == nullptr) {
          LOG_ERROR("[{}]- fail to create input stream desc", m_dec_name);
          return false;
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
715
      }
4061a3c3   Hu Chunming   更换decoder
716
717
718
719
720
      aclError ret = acldvppSetStreamDescEos(streamInputDesc, 1);
      if (ret != ACL_SUCCESS) {
          LOG_ERROR("[{}]- fail to set eos for stream desc, errorCode = {}", m_dec_name, static_cast<int32_t>(ret));
          (void)acldvppDestroyStreamDesc(streamInputDesc);
          return false;
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
721
722
      }
  
4061a3c3   Hu Chunming   更换decoder
723
724
725
726
727
728
729
      // send vdec eos frame. when all vdec callback are completed, aclvdecSendFrame can be returned.
      LOG_INFO("[{}]- send eos", m_dec_name);
      ret = aclvdecSendFrame(vdecChannelDesc, streamInputDesc, nullptr, nullptr, nullptr);
      (void)acldvppDestroyStreamDesc(streamInputDesc);
      if (ret != ACL_SUCCESS) {
          LOG_ERROR("[{}]- fail to send eos frame, ret={}", m_dec_name, ret);
          return false;
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
730
      }
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
731
  
4061a3c3   Hu Chunming   更换decoder
732
      return true;
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
733
734
  }
  
4061a3c3   Hu Chunming   更换decoder
735
736
737
  void DvppSnapshot::release_dvpp(){
      if(m_context){
          aclError ret = aclrtDestroyContext(m_context);
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
738
          if(ret != ACL_ERROR_NONE){
4061a3c3   Hu Chunming   更换decoder
739
              LOG_ERROR("[{}]- aclrtDestroyContext failed !", m_dec_name);
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
740
          }
4061a3c3   Hu Chunming   更换decoder
741
          m_context = nullptr;
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
742
      }
4061a3c3   Hu Chunming   更换decoder
743
744
745
746
      
      if(m_dvpp_channel >= 0){
          DvppSourceManager* pSrcMgr = DvppSourceManager::getInstance();
  	    pSrcMgr->releaseChannel(m_dvpp_deviceId, m_dvpp_channel);
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
747
  
4061a3c3   Hu Chunming   更换decoder
748
          LOG_INFO("[{}]- release channel:{}.", m_dec_name, m_dvpp_channel);
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
749
  
4061a3c3   Hu Chunming   更换decoder
750
          m_dvpp_channel = -1;
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
751
      }
6fdcb6a5   Hu Chunming   初次提交,代码大体完成编写,完善中
752
  }