DvppGB28181Decoder.cpp 9.98 KB
//#include "LOG_manager.h"
#include <iostream>
#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 || 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);
	}

    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);

	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() {
    return nullptr;
}

void DvppGB28181Decoder::doRecode(RecoderInfo& recoderInfo) {

}

void DvppGB28181Decoder::set_mq_callback(std::function<bool(const char *msg)> mq_publish) {
    
}