DvppGB28181Decoder2.cpp 6.06 KB
//#include "LOG_manager.h"
#include <iostream>
#include "DvppGB28181Decoder2.h"
#include "common_header.h"


#define ECLOSED 0
#define ECLOSING 1
#define ERUNNING 2
#define EPAUSE 3
#define EINITED 4

static void RTP_Stream_CallBack(void* userdata, uint8_t* buf, int buf_size, uint64_t pts)
{
    DvppGB28181Decoder2* decoder = (DvppGB28181Decoder2*)userdata;
    decoder->stream_callback(buf, buf_size, pts);
}

static void RTP_Stream_End_CallBack(void* userdata)
{
    DvppGB28181Decoder2* decoder = (DvppGB28181Decoder2*)userdata;
    decoder->stream_end_callback();
}

DvppGB28181Decoder2::DvppGB28181Decoder2() {
	m_frameSkip = 1;
    m_dec_keyframe = false;
    m_post_decode_thread = 0;
}

DvppGB28181Decoder2::~DvppGB28181Decoder2()
{
    close();

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

void DvppGB28181Decoder2::close(){

    if (m_status == ECLOSED) return;
    
    m_status = ECLOSING;

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

    if(nullptr != m_rtpPtr){
        m_rtpPtr->Close();
        LOG_DEBUG("real decode thread exit success 2--{}", m_dec_name);

        delete m_rtpPtr;
        m_rtpPtr = nullptr;
    }

    rtpDecoder.Close();

    if (m_post_decode_thread != 0) {
		pthread_join(m_post_decode_thread,0);
        m_post_decode_thread = 0;
	}

    m_status = ECLOSED;

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

bool DvppGB28181Decoder2::init(FFDecConfig& cfg){

    m_rtpPtr = new RTPReceiver2();
    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 (!rtpDecoder.Init(cfg)) {
        return false;
    }

    rtpDecoder.SetFinishedCallback(RTP_Stream_End_CallBack, this);

    m_cfg = cfg;

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

    m_status = EINITED;

    return true;
}

bool DvppGB28181Decoder2::start() {

    m_status = ERUNNING;

    bool bRet = m_rtpPtr->Open(m_cfg.uri, !m_cfg.force_tcp);
    if(bRet && rtpDecoder.start()) {
        pthread_create(&m_post_decode_thread,0,
            [](void* arg)
            {
                DvppGB28181Decoder2* a=(DvppGB28181Decoder2*)arg;
                a->display_thread();
                return (void*)0;
            }
        ,this);

        return true;
    }

    close();

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

    return false;
}

void DvppGB28181Decoder2::setDecKeyframe(bool bKeyframe){
	m_dec_keyframe = bKeyframe;
}

void DvppGB28181Decoder2::stream_callback(uint8_t* buf, int buf_size, uint64_t pts) {
    if (m_status == EPAUSE) return;

    // 若设置为关键帧解码,非关键帧数据直接返回
    // if(m_dec_keyframe && !isKey) return;

    rtpDecoder.CacheBuffer(buf, buf_size);
}

void DvppGB28181Decoder2::display_thread(){
	
	int index = 0;
	while (isRunning())
	{
        auto mem = rtpDecoder.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));
	}

    decode_finished_cbk(m_finishedDecArg);

	LOG_INFO("[{}] - display thread exited.", m_dec_name);
}

void DvppGB28181Decoder2::stream_end_callback()
{
    LOG_INFO("[{}] - stream end.", m_dec_name);

    m_status = ECLOSING;

    return;
}

void DvppGB28181Decoder2::setPostDecArg(const void* postDecArg){
	m_postDecArg = postDecArg;
}

void DvppGB28181Decoder2::setFinishedDecArg(const void* finishedDecArg){
	m_finishedDecArg = finishedDecArg;
}

void DvppGB28181Decoder2::pause() {
    m_status = EPAUSE;
    LOG_INFO("[{}] - pause", m_dec_name);
}

void DvppGB28181Decoder2::resume() {
    m_status = ERUNNING;
    LOG_INFO("[{}] - resume", m_dec_name);
}

bool DvppGB28181Decoder2::isRunning(){
    if (m_status == ECLOSED || m_status == ECLOSING){
        return false;
    }
    return true;
}

bool DvppGB28181Decoder2::isFinished(){
    if (m_status == ECLOSED || m_status == ECLOSING){
        return true;
    }
    return false;
}

bool DvppGB28181Decoder2::isPausing(){
    if (m_status == EPAUSE){
        return true;
    }
    return false;
}

bool DvppGB28181Decoder2::getResolution( int &width, int &height ){
    width = frameW;
    height = frameH;
    return true;
}

bool DvppGB28181Decoder2::getOutResolution( int &width, int &height ) {
    width = frameW;
    height = frameH;
    return true;
}

float DvppGB28181Decoder2::fps() {
    return m_fps;
}

bool DvppGB28181Decoder2::isSurport(FFDecConfig& cfg){
    // 由于是否支持需要在拿到数据后才能断定,无法事先判断,所以这个地方默认返回true
    return true;
}

DeviceMemory* DvppGB28181Decoder2::snapshot() {

    DeviceMemory* snapshot_mem = nullptr;
    int loop_times = 0;
    while (isRunning()) {
        snapshot_mem = rtpDecoder.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 DvppGB28181Decoder2::doRecode(RecoderInfo& recoderInfo) {
    return rtpDecoder.doRecode(recoderInfo);
}

void DvppGB28181Decoder2::set_mq_callback(std::function<bool(const char *msg)> mq_publish) {
    rtpDecoder.set_mq_callback(mq_publish);
}