2#include "../../../Defines.h"
4#ifdef USE_CAMERA_MODULE
8CStreamer::CStreamer(SOCKET aClient, u_short width, u_short height) : m_Client(aClient)
10 printf(
"Creating TSP streamer\n");
19 m_TCPTransport =
false;
21 m_RtpSocket = NULLSOCKET;
22 m_RtcpSocket = NULLSOCKET;
29CStreamer::~CStreamer()
31 udpsocketclose(m_RtpSocket);
32 udpsocketclose(m_RtcpSocket);
35int CStreamer::SendRtpPacket(
unsigned const char * jpeg,
int jpegLen,
int fragmentOffset, BufPtr quant0tbl, BufPtr quant1tbl)
37#define KRtpHeaderSize 12
38#define KJpegHeaderSize 8
40#define MAX_FRAGMENT_SIZE 1100
41 int fragmentLen = MAX_FRAGMENT_SIZE;
42 if(fragmentLen + fragmentOffset > jpegLen)
43 fragmentLen = jpegLen - fragmentOffset;
45 bool isLastFragment = (fragmentOffset + fragmentLen) == jpegLen;
49 bool includeQuantTbl = quant0tbl && quant1tbl && fragmentOffset == 0;
50 uint8_t q = includeQuantTbl ? 128 : 0x5e;
52 static char RtpBuf[2048];
53 int RtpPacketSize = fragmentLen + KRtpHeaderSize + KJpegHeaderSize + (includeQuantTbl ? (4 + 64 * 2) : 0);
55 memset(RtpBuf,0x00,
sizeof(RtpBuf));
59 RtpBuf[2] = (RtpPacketSize & 0x0000FF00) >> 8;
60 RtpBuf[3] = (RtpPacketSize & 0x000000FF);
63 RtpBuf[5] = 0x1a | (isLastFragment ? 0x80 : 0x00);
64 RtpBuf[7] = m_SequenceNumber & 0x0FF;
65 RtpBuf[6] = m_SequenceNumber >> 8;
66 RtpBuf[8] = (m_Timestamp & 0xFF000000) >> 24;
67 RtpBuf[9] = (m_Timestamp & 0x00FF0000) >> 16;
68 RtpBuf[10] = (m_Timestamp & 0x0000FF00) >> 8;
69 RtpBuf[11] = (m_Timestamp & 0x000000FF);
77 RtpBuf[17] = (fragmentOffset & 0x00FF0000) >> 16;
78 RtpBuf[18] = (fragmentOffset & 0x0000FF00) >> 8;
79 RtpBuf[19] = (fragmentOffset & 0x000000FF);
87 RtpBuf[22] = m_width / 8;
88 RtpBuf[23] = m_height / 8;
97 int numQantBytes = 64;
98 RtpBuf[27] = 2 * numQantBytes;
102 memcpy(RtpBuf + headerLen, quant0tbl, numQantBytes);
103 headerLen += numQantBytes;
105 memcpy(RtpBuf + headerLen, quant1tbl, numQantBytes);
106 headerLen += numQantBytes;
111 memcpy(RtpBuf + headerLen,jpeg + fragmentOffset, fragmentLen);
112 fragmentOffset += fragmentLen;
118 socketpeeraddr(m_Client, &otherip, &otherport);
122 socketsend(m_Client,RtpBuf,RtpPacketSize + 4);
124 udpsocketsend(m_RtpSocket,&RtpBuf[4],RtpPacketSize, otherip, m_RtpClientPort);
126 return isLastFragment ? 0 : fragmentOffset;
129void CStreamer::InitTransport(u_short aRtpPort, u_short aRtcpPort,
bool TCP)
131 m_RtpClientPort = aRtpPort;
132 m_RtcpClientPort = aRtcpPort;
133 m_TCPTransport = TCP;
137 for (u_short P = 6970; P < 0xFFFE; P += 2)
139 m_RtpSocket = udpsocketcreate(P);
142 m_RtcpSocket = udpsocketcreate(P + 1);
146 m_RtcpServerPort = P+1;
151 udpsocketclose(m_RtpSocket);
152 udpsocketclose(m_RtcpSocket);
159u_short CStreamer::GetRtpServerPort()
161 return m_RtpServerPort;
164u_short CStreamer::GetRtcpServerPort()
166 return m_RtcpServerPort;
169void CStreamer::streamFrame(
unsigned const char *data, uint32_t dataLen, uint32_t curMsec)
172 m_prevMsec = curMsec;
175 uint32_t deltams = (curMsec >= m_prevMsec) ? curMsec - m_prevMsec : 100;
176 m_prevMsec = curMsec;
179 BufPtr qtable0, qtable1;
181 if(!decodeJPEGfile(&data, &dataLen, &qtable0, &qtable1)) {
182 printf(
"can't decode jpeg data\n");
188 offset = SendRtpPacket(data, dataLen, offset, qtable0, qtable1);
189 }
while(offset != 0);
192 uint32_t units = 90000;
193 m_Timestamp += (units * deltams / 1000);
196 if (m_SendIdx > 1) m_SendIdx = 0;
216bool findJPEGheader(BufPtr *start, uint32_t *len, uint8_t marker) {
218 unsigned const char *bytes = *start;
223 while(bytes - *start < *len) {
224 uint8_t framing = *bytes++;
225 if(framing != 0xff) {
226 printf(
"malformed jpeg, framing=%x\n", framing);
229 uint8_t typecode = *bytes++;
230 if(typecode == marker) {
231 unsigned skipped = bytes - *start;
255 uint32_t len = bytes[0] * 256 + bytes[1];
261 printf(
"unexpected jpeg typecode 0x%x\n", typecode);
267 printf(
"failed to find jpeg marker 0x%x", marker);
274void skipScanBytes(BufPtr *start) {
275 BufPtr bytes = *start;
278 while(*bytes++ != 0xff);
285void nextJpegBlock(BufPtr *bytes) {
286 uint32_t len = (*bytes)[0] * 256 + (*bytes)[1];
294bool decodeJPEGfile(BufPtr *start, uint32_t *len, BufPtr *qtable0, BufPtr *qtable1) {
296 unsigned const char *bytes = *start;
298 if(!findJPEGheader(&bytes, len, 0xd8))
304 BufPtr quantstart = *start;
305 uint32_t quantlen = *len;
306 if(!findJPEGheader(&quantstart, &quantlen, 0xdb)) {
307 printf(
"error can't find quant table 0\n");
312 *qtable0 = quantstart + 3;
313 nextJpegBlock(&quantstart);
314 if(!findJPEGheader(&quantstart, &quantlen, 0xdb)) {
315 printf(
"error can't find quant table 1\n");
320 *qtable1 = quantstart + 3;
321 nextJpegBlock(&quantstart);
324 if(!findJPEGheader(start, len, 0xda))
328 uint32_t soslen = (*start)[0] * 256 + (*start)[1];
333 BufPtr endmarkerptr = *start;
334 uint32_t endlen = *len;
336 skipScanBytes(&endmarkerptr);
337 if(!findJPEGheader(&endmarkerptr, &endlen, 0xd9))
342 *len = endmarkerptr - *start;