typedef unsigned short WORD;
typedef unsigned long DWORD;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef unsigned __int64 uint64_t;
typedef unsigned char u_int8_t;
typedef unsigned short u_int16_t;
typedef unsigned int u_int32_t;
typedef unsigned __int64 u_int64_t;
typedef struct
{
WORD cc: 4; /* csrc count */
WORD ext: 1; /* header extension flag */
WORD pad: 1; /* padding flag - for encryption */
WORD ver: 2; /* protocal version */
WORD pt: 7; /* payload type */
WORD mk: 1; /* marker bit - for profile */
WORD seq; /* sequence number of this packet */
DWORD ts; /* timestamp of this packet */
DWORD ssrc; /* source of packet */
} RTP_HEADER;
#define RTP_SEND_SIZE (1440)
int trimStartCode(uint8_t *buf, int len)
{
uint8_t *ptr = buf;
if (len < 4) return 0;
// trying to find 0x00 0x00 ... 0x01 pattern
// find first 0x00 0x00 bytes
if (ptr[0] == 0x00 && ptr[1] == 0x00) {
// find first 0x01
while (*ptr == 0x00 && ptr < buf+len-1)
ptr++;
if (*ptr != 0x01) { // error - invalid stream
DPRINTF("invalid stream, 0x%02x\n", *ptr);
ptr = buf;
} else {
ptr++;
}
}
return ptr-buf;
}
void RTPSender::resetRtpHeader(uint8_t payload, uint8_t marker, uint32_t timestamp)
{
RTP_HEADER *pRtpHeader = (RTP_HEADER *)m_pRtpSendBuffer;
memset(pRtpHeader, 0, sizeof(RTP_HEADER));
pRtpHeader->ver = 2;
pRtpHeader->pt = payload;
pRtpHeader->mk = marker;
pRtpHeader->ts = htonl(timestamp);
uint16_t seqNum = 0;
seqNum = m_nSequenceNum++;
if (m_nSequenceNum >= 0xffff)
m_nSequenceNum = 0;
pRtpHeader->seq = htons(seqNum);
}
uint32_t RTPSender::convertToRTPTimestamp(unsigned int frequency, __int64 timestamp)
{
__int64 rtp_timestamp = (__int64)frequency * timestamp / (__int64)1000;
return rtp_timestamp;
}
int H264Sender::sendRtpData(MediaBuffer *pBuffer)
{
RTP_HEADER *pRtpHeader = (RTP_HEADER *)m_pRtpSendBuffer;
int offset = trimStartCode(pBuffer->data, pBuffer->size);
int bytesToSend = pBuffer->size-offset;
uint8_t *pSrc = &pBuffer->data[offset];
uint8_t *pDest = (uint8_t *)m_pRtpSendBuffer;
int rtphdr_size = sizeof(RTP_HEADER);
int pktcount = 0;
const char *track = "track1";
uint32_t timestamp = convertToRTPTimestamp(m_nTimestampFrequency, pBuffer->dts);
int sendToLen;
while (bytesToSend > RTP_SEND_SIZE)
{
resetRtpHeader(m_nPayloadType, 0, timestamp);
pDest = (uint8_t *)&m_pRtpSendBuffer[rtphdr_size];
pDest[0] = (pSrc[0] & 0xE0) | 28;
if (pktcount == 0) {
memcpy(&pDest[1], pSrc, RTP_SEND_SIZE);
pDest[1] = 0x80 | (pSrc[0] & 0x1F);
sendToLen = RTP_SEND_SIZE + rtphdr_size + 1;
} else {
pDest[1] = pSrc[0] & 0x1F;
memcpy(&pDest[2], pSrc, RTP_SEND_SIZE);
sendToLen = RTP_SEND_SIZE + rtphdr_size + 2;
}
pSrc += RTP_SEND_SIZE;
m_pServerSession->sendClientRtp(track, m_pRtpSendBuffer, sendToLen);
bytesToSend -= RTP_SEND_SIZE;
pktcount++;
}
if (bytesToSend > 0) {
resetRtpHeader(m_nPayloadType, 1, timestamp);
pDest = (uint8_t *)&m_pRtpSendBuffer[rtphdr_size];
if (pktcount == 0) {
memcpy(pDest, pSrc, bytesToSend);
sendToLen = bytesToSend + rtphdr_size;
} else { // FU-A last packet
pDest[0] = 0x20 | 28;
pDest[1] = 0x40;
memcpy(&pDest[2], pSrc, bytesToSend);
sendToLen = bytesToSend + rtphdr_size + 2;
}
m_pServerSession->sendClientRtp(track, m_pRtpSendBuffer, sendToLen);
}
return 0;
}
2014년 12월 4일 목요일
H.264 RFC3984 NAL 패킷전송
피드 구독하기:
글 (Atom)