//#include "LOG_manager.h" #include #include "DvppGB28181Decoder.h" extern "C" { #include "libavutil/avstring.h" #include "libavformat/avformat.h" #include "libswscale/swscale.h" } #include"RTPTcpReceiver.h" #include"RTPUdpReceiver.h" #include "common_header.h" // #include "../nvdec/FFCuContextManager.h" // #include "../nvdec/GpuRgbMemory.hpp" // #include "../nvdec/cuda_kernels.h" #define ECLOSED 0 #define ECLOSING 1 #define ERUNNING 2 #define EPAUSE 3 #define EINITED 4 static void RTP_Stream_CallBack(void* userdata, int videoType, char* data, int len, int isKey, uint64_t pts, uint64_t localPts) { DvppGB28181Decoder* decoder = (DvppGB28181Decoder*)userdata; decoder->stream_callback(videoType, data, len, isKey, pts, localPts); } static void RTP_Stream_End_CallBack(void* userdata) { DvppGB28181Decoder* decoder = (DvppGB28181Decoder*)userdata; decoder->stream_end_callback(); } DvppGB28181Decoder::DvppGB28181Decoder() { m_frameSkip = 1; m_dec_keyframe = false; m_post_decode_thread = 0; } DvppGB28181Decoder::~DvppGB28181Decoder() { close(); // if (m_pAVCodecCtx) { // avcodec_close(m_pAVCodecCtx); // avcodec_free_context(&m_pAVCodecCtx); // } m_dec_keyframe = false; LOG_INFO("destroy OK--{}", m_dec_name); } void DvppGB28181Decoder::close(){ if (m_status == ECLOSED) 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); m_post_decode_thread = 0; } streamDecoder.Close(); m_status = ECLOSED; LOG_INFO("解码器关闭成功 --{}", m_dec_name); } bool DvppGB28181Decoder::init(FFDecConfig& cfg){ if(cfg.force_tcp){ m_rtpPtr = new RTPTcpReceiver(); }else{ m_rtpPtr = new RTPUdpReceiver(); } if(nullptr == m_rtpPtr){ return false; } m_dec_name = cfg.dec_name; m_frameSkip = cfg.skip_frame; if (m_frameSkip < 1) m_frameSkip = 1; m_gpuid = atoi(cfg.gpuid.c_str()); m_rtpPtr->SetOutputCallback(RTP_Stream_CallBack, this); m_rtpPtr->SetVodEndCallback(RTP_Stream_End_CallBack, this); post_decoded_cbk = cfg.post_decoded_cbk; decode_finished_cbk = cfg.decode_finished_cbk; if (!streamDecoder.Init(cfg)) { return false; } m_cfg = cfg; LOG_INFO("init - {} ", m_dec_name); m_status = EINITED; return true; } bool DvppGB28181Decoder::start() { m_status = ERUNNING; bool bRet = m_rtpPtr->Open(m_cfg.uri); if(bRet){ pthread_create(&m_post_decode_thread,0, [](void* arg) { DvppGB28181Decoder* a=(DvppGB28181Decoder*)arg; a->display_thread(); return (void*)0; } ,this); return true; } close(); LOG_ERROR("[{}] - rtp receiver open failed !", m_dec_name); return bRet; } void DvppGB28181Decoder::setDecKeyframe(bool bKeyframe){ m_dec_keyframe = bKeyframe; } void DvppGB28181Decoder::stream_callback(int videoType, char* data, int len, int isKey, uint64_t pts, uint64_t localPts) { 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; } streamDecoder.SendData(videoType, data, len, isKey, pts); // AVPacket* pkt = av_packet_alloc(); // av_init_packet(pkt); // pkt->size = len; // pkt->data = (uint8_t*)data; // // ffmpeg 解码 // ff_decode(videoType, pkt); // av_packet_free(&pkt); // pkt = nullptr; } int DvppGB28181Decoder::ff_decode(int videoType, AVPacket* pkt) { // 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); // return; // } // } // m_fps = av_q2d(m_pAVCodecCtx->framerate); // 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 {}--{}", m_dec_name, gpuFrame->width, gpuFrame->height, frameW, frameH); // av_frame_free(&gpuFrame); // gpuFrame = nullptr; // return; // } // av_frame_free(&gpuFrame); // gpuFrame = nullptr; } void DvppGB28181Decoder::display_thread(){ int index = 0; while (isRunning()) { auto mem = streamDecoder.GetFrame(); if(mem) { if ((m_frameSkip == 1 || index % m_frameSkip == 0) && post_decoded_cbk){ post_decoded_cbk(m_postDecArg, mem); } else { delete mem; mem = nullptr; } index++; if(index >= 100000){ index = 0; } } std::this_thread::sleep_for(std::chrono::milliseconds(10)); } LOG_INFO("[{}] - display thread exited.", m_dec_name); } void DvppGB28181Decoder::stream_end_callback() { LOG_INFO("[{}] - send_video_eof", m_dec_name); m_status = ECLOSING; decode_finished_cbk(m_finishedDecArg); return; } void DvppGB28181Decoder::setPostDecArg(const void* postDecArg){ m_postDecArg = postDecArg; } void DvppGB28181Decoder::setFinishedDecArg(const void* finishedDecArg){ m_finishedDecArg = finishedDecArg; } void DvppGB28181Decoder::pause() { m_status = EPAUSE; LOG_INFO("[{}] - pause", m_dec_name); } void DvppGB28181Decoder::resume() { m_status = ERUNNING; LOG_INFO("[{}] - resume", m_dec_name); } bool DvppGB28181Decoder::isRunning(){ if (m_status == ECLOSED || m_status == ECLOSING){ return false; } return true; } bool DvppGB28181Decoder::isFinished(){ if (m_status == ECLOSED || m_status == ECLOSING){ return true; } return false; } bool DvppGB28181Decoder::isPausing(){ if (m_status == EPAUSE){ return true; } return false; } bool DvppGB28181Decoder::getResolution( int &width, int &height ){ width = frameW; height = frameH; return true; } bool DvppGB28181Decoder::getOutResolution( int &width, int &height ) { width = frameW; height = frameH; return true; } float DvppGB28181Decoder::fps() { return m_fps; } bool DvppGB28181Decoder::isSurport(FFDecConfig& cfg){ // 由于是否支持需要在拿到数据后才能断定,无法事先判断,所以这个地方默认返回true return true; } int DvppGB28181Decoder::getCachedQueueLength(){ return m_rtpPtr->GetPsFrameListSize(); } DeviceMemory* DvppGB28181Decoder::snapshot() { DeviceMemory* snapshot_mem = nullptr; int loop_times = 0; while (isRunning()) { snapshot_mem = streamDecoder.GetFrame(); if (snapshot_mem) { break; } loop_times++; if(loop_times > 100) { // 1s都没截取到图,退出 break; } std::this_thread::sleep_for(std::chrono::milliseconds(10)); } return snapshot_mem; } void DvppGB28181Decoder::doRecode(RecoderInfo& recoderInfo) { return streamDecoder.doRecode(recoderInfo); } void DvppGB28181Decoder::set_mq_callback(std::function mq_publish) { streamDecoder.set_mq_callback(mq_publish); }