RTPReceiver.h
4.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
#ifndef _RTP_RECEIVER_H_
#define _RTP_RECEIVER_H_
#include "demuxer.h"
#include "buffer.h"
#include "rtpudpv4transmitter.h"
#include "rtpipv4address.h"
#include "rtpsessionparams.h"
#include "rtpsession.h"
#include "rtppacket.h"
#include <queue>
#include <iostream>
#include <atomic>
#include <thread>
#include <string>
#include <mutex>
#define OUTTIME_RTCP 30*1000
#define PAYLOAD 99
#define PAYLOAD_PS 96
#define PAYLOAD_H264 98
#define PAYLOAD_MP4 97
#define UDP_SIZE 1400
#define MIN_PORT 10000
#define MAX_PORT 60000
#define RTP_MAX_PACKET_LEN 1450
using namespace jrtplib;
using namespace std;
typedef unsigned char BYTE;
/** 视频数据回调
*
* @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);
int AllocRtpPort(void);
class MyRTPSession : public RTPSession
{
public:
MyRTPSession() {}
virtual ~MyRTPSession() {}
private:
virtual void OnRTPPacket(RTPPacket* pack, const RTPTime& receiverTime, const RTPAddress* senderAddress)
{
AddDestination(*senderAddress);
}
virtual void OnRTCPCompoundPacket(RTCPCompoundPacket *pack, const RTPTime &receivetime,const RTPAddress *senderaddress)
{
//AddDestination(*senderaddress);
//const char* name = "hi~";
//SendRTCPAPPPacket(0, (const uint8_t*)name, "keeplive", 8);
//printf("send rtcp app");
}
};
// 标识帧, 注意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
{
RTPReceiver(const RTPReceiver& other);
RTPReceiver& operator= (const RTPReceiver& other);
public:
RTPReceiver();
~RTPReceiver();
bool Open(uint16_t localPort);
bool IsOpened() const;
void Close();
int GetPsFrameListSize();
void ClearPsVideoFrameList();
void OnPsDemux(unsigned char streamId, BYTE *data, int len, bool key, uint64_t pts, uint64_t localPts);
void SetOutputCallback(CallBack_Stream cb, void* param);
void SetVodEndCallback(CallBack_VodFileEnd cb, void* param);
CallBack_VodFileEnd GetVodEndFunc(){ return m_hVodEndFunc; }
void *GetUsrParam(){ return m_usrParam; }
void SetDeviceID(string deviceID){this->m_deviceID = deviceID; }
private:
static int rtp_revc_thread_(void* param);
static int ps_demuxer_thread_(void* param);
static int ps_decode_thread_(void* param);
int OnRtpRecv();
int OnPsProcess();
int OnDecodeProcess();
private:
std::thread m_rtpThread; // RTP接收线程
std::thread m_psThread; // PS解包线程
uint16_t m_localPort; // RTP接收端口
MyRTPSession m_rtpSession; // RTP会话
std::atomic_bool m_bRtpExit; // 标识RTP收包线程闭
std::atomic_bool m_bPsExit; // 标识PS解包线程关闭
std::queue<Frame*> m_psVideoFrames;
mutex m_psFrameMutex;
CMpeg2Demux m_psParser;
void* m_usrParam;
std::atomic_bool m_bOpened;
CallBack_Stream m_h264DataFunc; // 视频流回调
CallBack_VodFileEnd m_hVodEndFunc; // 录像流结束回调
CBuffer m_SliceBuf;
uint64_t m_LastPTS;
bool m_LastIsKeyFrame;
unsigned char m_LastStreamType;
int64_t m_idleCount;
int64_t m_noDataCount;//线程计数,用于打开流成功但是实际没流过来
string m_deviceID;
int64_t m_notToDecodCount{0};//线程计数,用来代表多长时间没有调用解码回调,针对大华相机
};
#endif // _RTP_RECEIVER_H_