RTPReceiver.h 3.38 KB
#ifndef _RTP_RECEIVER_H_
#define _RTP_RECEIVER_H_

#include "buffer.h"
#include "demuxer.h"
#include "rtppacket.h"
#include <stdint.h>
#include <mutex>
#include <queue>
#include <atomic>
#include <thread>

typedef unsigned char BYTE;

using namespace jrtplib;
using namespace std;

/** 视频数据回调
*
*  @param videoType [in] 视频类型 音频-0xC0、h264-0x1B、MPEG4-0x01、SVAC-0x80
*  @param data      [in] 视频数据
*  @param len       [in] 视频数据长度
*  @param isKey     [in] 是否为关键帧
*  @param pts       [in] 时间戳
*/
typedef void(*CallBack_Stream)(void* userdata, int videoType, char* data, int len, int isKey, uint64_t pts, uint64_t localPts);

/** 录像回放完成回调消息通知
*/
typedef void(*CallBack_VodFileEnd)(void* userdata);

/** 
 * 请求流
*/
typedef bool(*CallBack_Request_Stream)(const char* deviceId);

// 标识帧, 注意buffer需要自己开辟和释放
struct Frame {
	Frame() { buf_ = NULL; len_ = 0; }
	~Frame() {
		if (buf_ != nullptr)
		{
			free(buf_);
			buf_ = nullptr;
		}
	}
	Frame(BYTE* buf, int len, bool key) : buf_(buf), len_(len), key_(key) {}
	BYTE* buf_;
	int	  len_;
	bool  key_{};
};

class FrameToDecode
{
public:
	FrameToDecode()
		: m_SliceBuf(0)
		, m_localPts(0)
		, m_LastPTS(-1)
		, m_LastIsKeyFrame(0) {}		
	FrameToDecode(unsigned char m_streamId)
		: m_SliceBuf(0)
		, m_localPts(0)
		, m_LastPTS(-1)
		, m_LastIsKeyFrame(0) 
		, m_streamId (m_streamId) {}

	void operator=(FrameToDecode &temp)
	{
		m_SliceBuf = temp.m_SliceBuf;
		m_streamId = temp.m_streamId;
		m_localPts = temp.m_localPts;
		m_LastPTS = temp.m_LastPTS;
		m_LastIsKeyFrame = temp.m_LastIsKeyFrame;
	}
		
	CBuffer m_SliceBuf;
	unsigned char m_streamId{};
	uint64_t m_localPts;
	uint64_t m_LastPTS;
	bool m_LastIsKeyFrame;
};

class RTPReceiver{

public:
    RTPReceiver();
    virtual ~RTPReceiver();

    virtual bool Open(uint16_t localPort) = 0;
	virtual bool IsOpened() = 0;
	virtual void Close() = 0;

	void SetVodEndCallback(CallBack_VodFileEnd cb, void* param);

    void SetOutputCallback(CallBack_Stream cb, void* param);

    void SetRequestStreamCallback(CallBack_Request_Stream cb);

    void SetDeviceID(string deviceID);

    int GetPsFrameListSize();

public:
    void OnPsDemux(unsigned char streamId, BYTE *data, int len, bool key, uint64_t pts, uint64_t localPts);
    int OnPsProcess();
    void ClearPsVideoFrameList();
    int ParsePacket(RTPPacket* packet);

public:
    int InitPS();
    void ClosePsThread();
    void *GetUsrParam(){ return m_usrParam; }

public:
    CBuffer         m_SliceBuf;
	uint64_t        m_LastPTS;
	bool            m_LastIsKeyFrame;
    unsigned char   m_LastStreamType;

    int64_t         m_notToDecodCount{0};//线程计数,用来代表多长时间没有调用解码回调,针对大华相机

    void*           m_usrParam;
    CallBack_Stream   m_h264DataFunc;				// 视频流回调

    std::queue<Frame*>	m_psVideoFrames;
	mutex m_psFrameMutex;

    string m_deviceID;

    CMpeg2Demux       m_psParser;
    std::atomic_bool               m_bPsExit; 					// 标识PS解包线程关闭

    uint32_t lastPts{0};
    uint64_t last_recv_ts{0};
	int offset{0};
	int mark{0};
	BYTE* recvTmpBuf{nullptr};

    std::thread*	      m_psThreadPtr; 					// PS解包线程

    CallBack_VodFileEnd m_hVodEndFunc;				// 录像流结束回调
    CallBack_Request_Stream m_callback_request_stream;  //请求流回调
};

#endif  // _RTP_RECEIVER_H_