Blame view

src/decoder/gb28181/DvppGB28181Decoder.cpp 9.36 KB
c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
1
2
  //#include "LOG_manager.h"

  #include <iostream>

74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
3
  #include "DvppGB28181Decoder.h"

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  

  

  

  extern "C" {

      #include "libavutil/avstring.h"

      #include "libavformat/avformat.h"

      #include "libswscale/swscale.h"

  }

  

  #include"RTPTcpReceiver.h"

  #include"RTPUdpReceiver.h"

  

  #include <cuda_runtime.h>

  

  #include "common_header.h"

  

74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
20
21
22
  // #include "../nvdec/FFCuContextManager.h"

  // #include "../nvdec/GpuRgbMemory.hpp"

  // #include "../nvdec/cuda_kernels.h"

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
23
24
25
26
27
28
29
30
  

  #define ECLOSED 0

  #define ECLOSING 1

  #define ERUNNING 2

  #define EPAUSE 3

  

  static void RTP_Stream_CallBack(void* userdata, int videoType, char* data, int len, int isKey, uint64_t pts, uint64_t localPts)

  {

74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
31
      DvppGB28181Decoder* decoder = (DvppGB28181Decoder*)userdata;

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
32
33
34
35
36
      decoder->stream_callback(videoType, data, len, isKey, pts, localPts);

  }

  

  static void RTP_Stream_End_CallBack(void* userdata)

  {

74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
37
      DvppGB28181Decoder* decoder = (DvppGB28181Decoder*)userdata;

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
38
39
40
      decoder->stream_end_callback();

  }

  

74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
41
  DvppGB28181Decoder::DvppGB28181Decoder() {

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
42
  	m_frameSkip = 1;

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
43
44
45
46
      m_dec_keyframe = false;

      m_post_decode_thread = 0;

  }

  

74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
47
  DvppGB28181Decoder::~DvppGB28181Decoder()

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
48
49
50
51
52
53
54
55
56
57
58
59
60
  {

      close();

  	

      if (m_pAVCodecCtx) {

          avcodec_close(m_pAVCodecCtx);

          avcodec_free_context(&m_pAVCodecCtx);

      }

  

      m_dec_keyframe = false;

      

      LOG_INFO("destroy OK--{}", m_dec_name);

  }

  

74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
61
  void DvppGB28181Decoder::close(){

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
      if (m_status == ECLOSED || m_status == ECLOSING) return ;

      

      m_status = ECLOSING;

  

      LOG_DEBUG("real decode thread exit success 1--{}", m_dec_name);

  

      if(nullptr != m_rtpPtr){

          if (m_rtpPtr->IsOpened()) {

              m_rtpPtr->Close();

              LOG_DEBUG("real decode thread exit success 2--{}", m_dec_name);

          }

  

          delete m_rtpPtr;

          m_rtpPtr = nullptr;

      }

  

      if (gpu_options) av_dict_free(&gpu_options);

  

      if (m_post_decode_thread != 0)

  	{

  		pthread_join(m_post_decode_thread,0);

  	}

  

      while(mFrameQueue.size() > 0){

  		AVFrame * gpuFrame = mFrameQueue.front();

  		av_frame_free(&gpuFrame); 

  		mFrameQueue.pop();

  	}

  

      m_status = ECLOSED;

  

      LOG_INFO("解码器关闭成功 --{}", m_dec_name);

  }

  

74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
96
  bool DvppGB28181Decoder::init(FFDecConfig& cfg){

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
      if(cfg.force_tcp){

          m_rtpPtr = new RTPTcpReceiver();

      }else{

          m_rtpPtr = new RTPUdpReceiver();

      }

      if(nullptr == m_rtpPtr){

          return false;

      }

  

      m_dec_name = cfg.uri;

  	m_frameSkip = cfg.skip_frame;

      if (m_frameSkip < 1) m_frameSkip = 1;

  

      m_gpuid = atoi(cfg.gpuid.c_str());

  

74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
112
113
      m_rtpPtr->SetOutputCallback(RTP_Stream_CallBack, this);

  	m_rtpPtr->SetVodEndCallback(RTP_Stream_End_CallBack, this);

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
114
115
116
  

      post_decoded_cbk = cfg.post_decoded_cbk;

      decode_finished_cbk = cfg.decode_finished_cbk;

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
117
  

74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
118
119
120
      if (!streamDecoder.Init(cfg)) {

          return false;

      }

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
121
122
123
  

      m_cfg = cfg;

  

74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
124
      LOG_INFO("init - {} ", m_dec_name);

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
125
126
127
128
  

      return true;

  }

  

74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
129
  bool DvppGB28181Decoder::start() {

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
130
131
132
  

      m_status = ERUNNING;

  

74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
133
      bool bRet = m_rtpPtr->Open(m_dec_name);

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
134
135
136
137
      if(bRet){

          pthread_create(&m_post_decode_thread,0,

              [](void* arg)

              {

74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
138
139
                  DvppGB28181Decoder* a=(DvppGB28181Decoder*)arg;

                  a->display_thread();

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
140
141
142
143
                  return (void*)0;

              }

          ,this);

      }

74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
144
145
146
  

      LOG_ERROR("[{}] - rtp receiver open failed !", m_dec_name);

  

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
147
148
149
      return bRet;

  }

  

74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
150
  void DvppGB28181Decoder::setDecKeyframe(bool bKeyframe){

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
151
152
153
  	m_dec_keyframe = bKeyframe;

  }

  

74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
154
  void DvppGB28181Decoder::stream_callback(int videoType, char* data, int len, int isKey, uint64_t pts, uint64_t localPts) {

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
      if (m_status == EPAUSE) return;

  

      // 若设置为关键帧解码,非关键帧数据直接返回

      if(m_dec_keyframe && !isKey) return;

      

      if (len <= 0) {

          if (data == nullptr && pts == -1) {

              LOG_INFO("frame callback EOF!");

  			post_decoded_cbk(m_postDecArg, nullptr);

              return ;

          }

          LOG_INFO("frame data is zero --{}", m_dec_name);

          return;

      }

  

74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
170
      streamDecoder.SendData(videoType, data, len, isKey, pts);

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
171
  

74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
172
173
      // AVPacket* pkt = av_packet_alloc();

  	// av_init_packet(pkt);

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
174
  

74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
175
176
      // pkt->size = len;

      // pkt->data = (uint8_t*)data;

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
177
  

74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
178
179
180
181
182
      // // ffmpeg 解码

      // ff_decode(videoType, pkt);

  

      // av_packet_free(&pkt);

      // pkt = nullptr;

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
183
184
185
  

  }

  

74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
186
187
  int DvppGB28181Decoder::ff_decode(int videoType, AVPacket* pkt) {

  

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
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
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
      if (m_pAVCodecCtx == nullptr) {

          LOG_INFO("frame data is zero --{}", m_dec_name);

  		if (VIDEO_TYPE_H264 == videoType) {

              if (m_gpuid >= 0){

                  m_pAVCodec = avcodec_find_decoder_by_name("h264_cuvid");

              }

              else{

  				m_pAVCodec = avcodec_find_decoder(AV_CODEC_ID_H264);

  			}

  			LOG_INFO("m_avCodecName is H264");		

  		}

  		else if (VIDEO_TYPE_H265 == videoType)

  		{

              if (m_gpuid >= 0){

                  m_pAVCodec = avcodec_find_decoder_by_name("hevc_cuvid");

              }

              else{

                  m_pAVCodec = avcodec_find_decoder(AV_CODEC_ID_H265);

              }

  			LOG_INFO("m_avCodecName is H265");

  		}

  		else{

  			LOG_INFO("m_avCodecName is unknown, videoType is {}", videoType);

  		}

  

  		if (!m_pAVCodec)

  		{

  			LOG_ERROR("frameCallback frame decode error, ERROR_DECODER_NOT_FOUND");

  			return;

  		}

  

          m_pAVCodecCtx = avcodec_alloc_context3(m_pAVCodec);

  

          if (m_gpuid >= 0) {

              char gpui[8] = { 0 };

              sprintf(gpui, "%d", m_gpuid);

              av_dict_set(&gpu_options, "gpu", gpui, 0);

  

              m_pAVCodecCtx->get_format = get_hw_format;

  

              FFCuContextManager* pCtxMgr = FFCuContextManager::getInstance();

              m_pAVCodecCtx->hw_device_ctx = av_buffer_ref(pCtxMgr->getCuCtx(gpui));

              if (nullptr == m_pAVCodecCtx->hw_device_ctx){

                  // TODO 这里应该抛出错误

                  return ;

              }

          }

  

          if (avcodec_open2(m_pAVCodecCtx, m_pAVCodec, &gpu_options) < 0)

  			return;

  	}

  

      //开始解码

      int ret = avcodec_send_packet(m_pAVCodecCtx, pkt);

      if (ret < 0) {

          //send_exception(RunMessageType::E2002, e_msg);

          LOG_ERROR("Real stream视频解码失败,请检查视频设备{}: avcodec_send_packet failed. ret={}", m_dec_name, ret);

          return;

      }

   

      if (frameW < 1) {

          frameW = m_pAVCodecCtx->width;

          frameH = m_pAVCodecCtx->height;

          if (frameW <= 0 || frameH <= 0) {

              LOG_ERROR("[{}] frame W or H is error! ({},{})", m_dec_name, frameW, frameH);

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
253
254
255
              return;

          }	

      }

74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
256
  

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
257
      m_fps = av_q2d(m_pAVCodecCtx->framerate);

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
  

      AVFrame* gpuFrame = av_frame_alloc();

      ret = avcodec_receive_frame(m_pAVCodecCtx, gpuFrame);

      if ((ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) || ret < 0){

          LOG_ERROR("{} - Failed to receive frame: {}", m_dec_name, ret);

          av_frame_free(&gpuFrame);

          gpuFrame = nullptr;

          return;

      }

      

      if (gpuFrame->width != frameW || gpuFrame->height != frameH){

          LOG_INFO("AVFrame is inconsistent: width is {}, height is {}; original frameW is {}, frameH is {}--{}", gpuFrame->width, gpuFrame->height, frameW, frameH , m_dec_name);

          av_frame_free(&gpuFrame);

          gpuFrame = nullptr;

          return;

      }

  

74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
275
276
      av_frame_free(&gpuFrame); 

      gpuFrame = nullptr;

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
277
278
  }

  

74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
279
  void DvppGB28181Decoder::display_thread(){

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
280
281
282
283
  	

  	int index = 0;

  	while (isRunning())

  	{

74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
284
285
286
287
288
          auto mem = streamDecoder.GetFrame();

          if(mem) {

              if ((m_frameSkip == 1 || index % m_frameSkip == 0) && post_decoded_cbk){

                  post_decoded_cbk(m_postDecArg, mem);

              }

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
289
  

74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
290
              index++;

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
291
292
293
              if(index >= 100000){

                  index = 0;

              }

74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
294
295
296
297
298
299
          } else {

              delete mem;

              mem = nullptr;

          }

  

          std::this_thread::sleep_for(std::chrono::milliseconds(10));

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
300
301
  	}

  

74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
302
  	LOG_INFO("display thread exited.");

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
303
304
  }

  

74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
305
  void DvppGB28181Decoder::stream_end_callback()

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
306
307
308
309
310
311
312
313
  {

      LOG_INFO("send_video_eof--{}", m_dec_name);

  

  	decode_finished_cbk(m_finishedDecArg);

  

      return;

  }

  

74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
314
  void DvppGB28181Decoder::setPostDecArg(const void* postDecArg){

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
315
316
317
  	m_postDecArg = postDecArg;

  }

  

74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
318
  void DvppGB28181Decoder::setFinishedDecArg(const void* finishedDecArg){

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
319
320
321
  	m_finishedDecArg = finishedDecArg;

  }

  

74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
322
  void DvppGB28181Decoder::pause() {

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
323
324
325
326
      m_status = EPAUSE;

      LOG_INFO("pause --{}", m_dec_name);

  }

  

74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
327
  void DvppGB28181Decoder::resume() {

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
328
329
330
331
      m_status = ERUNNING;

      LOG_INFO("resume --{}", m_dec_name);

  }

  

74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
332
  bool DvppGB28181Decoder::isRunning(){

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
333
334
335
336
337
338
      if (m_status == ECLOSED || m_status == ECLOSING){

          return false;

      }

      return true;

  }

  

74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
339
  bool DvppGB28181Decoder::isFinished(){

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
340
341
342
343
344
345
      if (m_status == ECLOSED || m_status == ECLOSING){

          return true;

      }

      return false;

  }

  

74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
346
  bool DvppGB28181Decoder::isPausing(){

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
347
348
349
350
351
352
      if (m_status == EPAUSE){

          return true;

      }

      return false;

  }

  

74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
353
  bool DvppGB28181Decoder::getResolution( int &width, int &height ){

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
354
355
356
357
358
      width = frameW;

      height = frameH;

      return true;

  }

  

74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
359
  float DvppGB28181Decoder::fps() {

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
360
361
362
      return m_fps;

  }

  

74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
363
  bool DvppGB28181Decoder::isSurport(FFDecConfig& cfg){

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
364
365
366
367
      // 由于是否支持需要在拿到数据后才能断定,无法事先判断,所以这个地方默认返回true

      return true;

  }

  

74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
368
  int DvppGB28181Decoder::getCachedQueueLength(){

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
369
      return m_rtpPtr->GetPsFrameListSize();

c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
370
  }