#include "FFDecoder.h" #include "./rtp/demuxer.h" #include "common_header.h" #include "../nvdec/FFCuContextManager.h" static AVPixelFormat get_hw_format(AVCodecContext *avctx, const AVPixelFormat *pix_fmts){ return AV_PIX_FMT_CUDA; } FFDecoder::FFDecoder(/* args */) { } FFDecoder::~FFDecoder() { } FrameData* FFDecoder::Decode(int videoType, char* data, int len, int isKey, uint64_t pts) { AVPacket* pkt = av_packet_alloc(); av_init_packet(pkt); pkt->size = len; pkt->data = (uint8_t*)data; // ffmpeg 解码 FrameData* frame_data = ff_decode(videoType, pkt); av_packet_free(&pkt); pkt = nullptr; frame_data.bKeyframe = (isKey != 0); frame_data.pts = pts; return frame_data; } FrameData* FFDecoder::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_devid >= 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_devid >= 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 nullptr;return; } m_pAVCodecCtx = avcodec_alloc_context3(m_pAVCodec); if (m_devid >= 0) { char gpui[8] = { 0 }; sprintf(gpui, "%d", m_devid); 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 nullptr; } } if (avcodec_open2(m_pAVCodecCtx, m_pAVCodec, &gpu_options) < 0) return nullptr; } //开始解码 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 nullptr; } } // m_fps = m_pAVCodecCtx->pkt_timebase.den == 0 ? 25.0 : av_q2d(m_pAVCodecCtx->pkt_timebase); m_fps = av_q2d(m_pAVCodecCtx->framerate); // LOG_DEBUG("frameW {}--frameH {}", frameW, frameH); FrameData* pData = new FrameData(); ret = avcodec_receive_frame(m_pAVCodecCtx, pData->frame); if ((ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) || ret < 0){ LOG_ERROR("{} - Failed to receive frame: {}", m_dec_name, ret); delete pData; pData = nullptr; return nullptr; } AVFrame* gpuFrame = pData->frame; 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); delete pData; pData = nullptr; return nullptr; } return pData; }