RTMPPacket与AVData之间的转换
2015-08-06 22:29
459 查看
1、RTMPPacket的结构:
typedef struct RTMPPacket
{
uint8_t m_headerType;
uint8_t m_packetType;
uint8_t m_hasAbsTimestamp; /* timestamp absolute or relative? */
int m_nChannel;
uint32_t m_nTimeStamp; /* timestamp */
int32_t m_nInfoField2; /* last 4 bytes in a long header */
uint32_t m_nBodySize;
uint32_t m_nBytesRead;
RTMPChunk *m_chunk;
char *m_body;
} RTMPPacket;
typedef struct RTMPChunk
{
int c_headerSize;
int c_chunkSize;
char *c_chunk;
char c_header[RTMP_MAX_HEADER_SIZE];
} RTMPChunk;
#define RTMP_MAX_HEADER_SIZE 18
2、AVData是一个类,它的数据成员:
private:
unsigned char*
m_pData;
int
m_nDataSize;
int m_nMaxDataSize;
int m_nHeadSize;
uint64_t
m_nTimeTick;
bool m_bKeyFrame;
bool m_bEncode;
int m_nWidth;
int m_nHeight;
int m_nStreamType;
//1 视频 0 音频
int m_nAVType;
bool m_bSign;
int m_nDuration;
std::string
m_strIndexInfo;
3、音视频数据转AVData
bool SetData(int nAVType, unsigned char* pData, int nSize, uint64_t timetick, unsigned short nType,
bool bkeyFrame, unsigned short nCodeID, unsigned short nWidth,
unsigned short nHeight, bool bEncode, bool bClone = true)
{
m_nDuration = 0;
m_nAVType = nAVType;
m_bKeyFrame = bkeyFrame;
if (bClone)
{
if (em_avdata_video == m_nAVType)
{
m_nHeadSize = 3;
if (bkeyFrame)
{
m_nHeadSize = 8;
}
m_nDataSize = nSize + m_nHeadSize;
int nLen = m_nDataSize;
if (NULL != m_pData)
{
if (m_nDataSize > m_nMaxDataSize)
{
m_pData = (unsigned char*)realloc(m_pData, m_nDataSize);
m_nMaxDataSize = m_nDataSize;
}
}
else
{
m_pData = (unsigned char *)malloc(nLen);
m_nMaxDataSize = m_nDataSize;
}
if (m_pData == NULL)
{
return false;
}
memcpy(m_pData+m_nHeadSize,pData,nSize);
*(bool*)(m_pData) = bkeyFrame;
unsigned short nTick = (unsigned short)(timetick%100);
*(unsigned short*)(m_pData+1) = htons(nTick);
if (bkeyFrame)
{
*(unsigned char*)(m_pData+3) = nCodeID;
*(unsigned short*)(m_pData+4) = htons(nWidth);
*(unsigned short*)(m_pData+6) = htons(nHeight);
}
}
else if (em_avdata_audio == m_nAVType)
{
m_nHeadSize = 10;
m_nDataSize = nSize + m_nHeadSize;
short int nChannels = nType;
short int nSample_rate = nWidth;
short int nBit = nHeight;
short int nTick = (short int)timetick;
int nLen = m_nDataSize;
m_pData = (unsigned char *)malloc(nLen);
memcpy(m_pData+m_nHeadSize,pData,nSize);
*(unsigned short*)(m_pData) = htons(nCodeID);
*(unsigned short*)(m_pData+2) = htons(nChannels);
*(unsigned short*)(m_pData+4) = htons(nSample_rate);
*(unsigned short*)(m_pData+6) = htons(nBit);
*(unsigned short*)(m_pData+8) = htons(nTick);
}
}
else
{
m_nHeadSize = 0;
m_nDataSize = nSize;
m_pData = pData;
}
m_nTimeTick = timetick;
m_bEncode = bEncode;
m_nStreamType = nType;
m_nHeight = nHeight;
m_nWidth = nWidth;
return true;
}
这个函数相当于将数据pData根据不同的类型增加了一个头部
视频:0:bKeyFrame,1~2:timetick(3:codeid,4~5:nWidth,6~7:nHeight)
音频:0~1:codeid,2~3:nChannels(nType),4~5:samerate(nWidth),6~7nBit(nHeigt),8~9:timetick
4、AVData转unsigned int nPacketType,unsigned char *data,unsigned int size,unsigned int nTimestamp
void libRtmpProxy::SendRtmpQueue()
{
AVData* pAVData = m_pDataPool->GetDataBuffer();
if (pAVData)
{
refguard g(pAVData);
unsigned char* pBuff = pAVData->GetAVData();
int nBufLen = pAVData->GetAVDataSize();
int nType = pAVData->GetAVDataType();
unsigned int unTimestamp = pAVData->GetTimeTick();
bool bIsKeyFrame = pAVData->IsKeyFrame();
unsigned char *body = new unsigned char[nBufLen+9];
int i = 0;
if(bIsKeyFrame)
{
body[i++] = 0x17;// 1:Iframe 7:AVC
}
else
{
body[i++] = 0x27;// 2:Pframe 7:AVC
}
body[i++] = 0x01;// AVC NALU
body[i++] = 0x00;
body[i++] = 0x00;
body[i++] = 0x00;
// NALU size
body[i++] = nBufLen>>24;
body[i++] = nBufLen>>16;
body[i++] = nBufLen>>8;
body[i++] = nBufLen&0xff;
// NALU data
memcpy(&body[i],pBuff,nBufLen);
int nPacketType = RTMP_PACKET_TYPE_VIDEO;
if (nType == 0)
{
nPacketType = RTMP_PACKET_TYPE_AUDIO;
}
bool bRet = SendPacket(nPacketType, body,i+nBufLen, unTimestamp);
delete[] body;
}
}
这个函数相当于取出AVData的属性,将原来加入的头部删除,增加了一个9字节长度的头部
(音频也有I、P帧吗?)
5、由属性转为RTMPPacket
int libRtmpProxy::SendPacket(unsigned int nPacketType,unsigned char *data,unsigned int size,unsigned int nTimestamp)
{
RTMPPacket packet;
RTMPPacket_Reset(&packet);
RTMPPacket_Alloc(&packet,size);
packet.m_packetType = nPacketType;
packet.m_nChannel = 0x04;
packet.m_headerType = RTMP_PACKET_SIZE_LARGE;
packet.m_nTimeStamp = nTimestamp;
packet.m_nInfoField2 = m_pRtmp->m_stream_id;
packet.m_nBodySize = size;
memcpy(packet.m_body,data,size);
int nRet = RTMP_SendPacket(m_pRtmp,&packet,0);
RTMPPacket_Free(&packet);
return nRet;
}
此函数向packet直接赋属性值,copy第4步准备的整个包(包括头部)
6、RTMPPacket转AVData的思路
6.1直接得到属性,从头部可取得属性,删除9字节的头部,
typedef struct RTMPPacket
{
uint8_t m_headerType;
uint8_t m_packetType;
uint8_t m_hasAbsTimestamp; /* timestamp absolute or relative? */
int m_nChannel;
uint32_t m_nTimeStamp; /* timestamp */
int32_t m_nInfoField2; /* last 4 bytes in a long header */
uint32_t m_nBodySize;
uint32_t m_nBytesRead;
RTMPChunk *m_chunk;
char *m_body;
} RTMPPacket;
typedef struct RTMPChunk
{
int c_headerSize;
int c_chunkSize;
char *c_chunk;
char c_header[RTMP_MAX_HEADER_SIZE];
} RTMPChunk;
#define RTMP_MAX_HEADER_SIZE 18
2、AVData是一个类,它的数据成员:
private:
unsigned char*
m_pData;
int
m_nDataSize;
int m_nMaxDataSize;
int m_nHeadSize;
uint64_t
m_nTimeTick;
bool m_bKeyFrame;
bool m_bEncode;
int m_nWidth;
int m_nHeight;
int m_nStreamType;
//1 视频 0 音频
int m_nAVType;
bool m_bSign;
int m_nDuration;
std::string
m_strIndexInfo;
3、音视频数据转AVData
bool SetData(int nAVType, unsigned char* pData, int nSize, uint64_t timetick, unsigned short nType,
bool bkeyFrame, unsigned short nCodeID, unsigned short nWidth,
unsigned short nHeight, bool bEncode, bool bClone = true)
{
m_nDuration = 0;
m_nAVType = nAVType;
m_bKeyFrame = bkeyFrame;
if (bClone)
{
if (em_avdata_video == m_nAVType)
{
m_nHeadSize = 3;
if (bkeyFrame)
{
m_nHeadSize = 8;
}
m_nDataSize = nSize + m_nHeadSize;
int nLen = m_nDataSize;
if (NULL != m_pData)
{
if (m_nDataSize > m_nMaxDataSize)
{
m_pData = (unsigned char*)realloc(m_pData, m_nDataSize);
m_nMaxDataSize = m_nDataSize;
}
}
else
{
m_pData = (unsigned char *)malloc(nLen);
m_nMaxDataSize = m_nDataSize;
}
if (m_pData == NULL)
{
return false;
}
memcpy(m_pData+m_nHeadSize,pData,nSize);
*(bool*)(m_pData) = bkeyFrame;
unsigned short nTick = (unsigned short)(timetick%100);
*(unsigned short*)(m_pData+1) = htons(nTick);
if (bkeyFrame)
{
*(unsigned char*)(m_pData+3) = nCodeID;
*(unsigned short*)(m_pData+4) = htons(nWidth);
*(unsigned short*)(m_pData+6) = htons(nHeight);
}
}
else if (em_avdata_audio == m_nAVType)
{
m_nHeadSize = 10;
m_nDataSize = nSize + m_nHeadSize;
short int nChannels = nType;
short int nSample_rate = nWidth;
short int nBit = nHeight;
short int nTick = (short int)timetick;
int nLen = m_nDataSize;
m_pData = (unsigned char *)malloc(nLen);
memcpy(m_pData+m_nHeadSize,pData,nSize);
*(unsigned short*)(m_pData) = htons(nCodeID);
*(unsigned short*)(m_pData+2) = htons(nChannels);
*(unsigned short*)(m_pData+4) = htons(nSample_rate);
*(unsigned short*)(m_pData+6) = htons(nBit);
*(unsigned short*)(m_pData+8) = htons(nTick);
}
}
else
{
m_nHeadSize = 0;
m_nDataSize = nSize;
m_pData = pData;
}
m_nTimeTick = timetick;
m_bEncode = bEncode;
m_nStreamType = nType;
m_nHeight = nHeight;
m_nWidth = nWidth;
return true;
}
这个函数相当于将数据pData根据不同的类型增加了一个头部
视频:0:bKeyFrame,1~2:timetick(3:codeid,4~5:nWidth,6~7:nHeight)
音频:0~1:codeid,2~3:nChannels(nType),4~5:samerate(nWidth),6~7nBit(nHeigt),8~9:timetick
4、AVData转unsigned int nPacketType,unsigned char *data,unsigned int size,unsigned int nTimestamp
void libRtmpProxy::SendRtmpQueue()
{
AVData* pAVData = m_pDataPool->GetDataBuffer();
if (pAVData)
{
refguard g(pAVData);
unsigned char* pBuff = pAVData->GetAVData();
int nBufLen = pAVData->GetAVDataSize();
int nType = pAVData->GetAVDataType();
unsigned int unTimestamp = pAVData->GetTimeTick();
bool bIsKeyFrame = pAVData->IsKeyFrame();
unsigned char *body = new unsigned char[nBufLen+9];
int i = 0;
if(bIsKeyFrame)
{
body[i++] = 0x17;// 1:Iframe 7:AVC
}
else
{
body[i++] = 0x27;// 2:Pframe 7:AVC
}
body[i++] = 0x01;// AVC NALU
body[i++] = 0x00;
body[i++] = 0x00;
body[i++] = 0x00;
// NALU size
body[i++] = nBufLen>>24;
body[i++] = nBufLen>>16;
body[i++] = nBufLen>>8;
body[i++] = nBufLen&0xff;
// NALU data
memcpy(&body[i],pBuff,nBufLen);
int nPacketType = RTMP_PACKET_TYPE_VIDEO;
if (nType == 0)
{
nPacketType = RTMP_PACKET_TYPE_AUDIO;
}
bool bRet = SendPacket(nPacketType, body,i+nBufLen, unTimestamp);
delete[] body;
}
}
这个函数相当于取出AVData的属性,将原来加入的头部删除,增加了一个9字节长度的头部
(音频也有I、P帧吗?)
5、由属性转为RTMPPacket
int libRtmpProxy::SendPacket(unsigned int nPacketType,unsigned char *data,unsigned int size,unsigned int nTimestamp)
{
RTMPPacket packet;
RTMPPacket_Reset(&packet);
RTMPPacket_Alloc(&packet,size);
packet.m_packetType = nPacketType;
packet.m_nChannel = 0x04;
packet.m_headerType = RTMP_PACKET_SIZE_LARGE;
packet.m_nTimeStamp = nTimestamp;
packet.m_nInfoField2 = m_pRtmp->m_stream_id;
packet.m_nBodySize = size;
memcpy(packet.m_body,data,size);
int nRet = RTMP_SendPacket(m_pRtmp,&packet,0);
RTMPPacket_Free(&packet);
return nRet;
}
此函数向packet直接赋属性值,copy第4步准备的整个包(包括头部)
6、RTMPPacket转AVData的思路
6.1直接得到属性,从头部可取得属性,删除9字节的头部,
相关文章推荐
- 集中精力
- leetcode 80: Remove Duplicates from Sorted Array II
- 安卓设计架构
- Remove Nth Node From End of List
- 线程通信
- Struts 2中的constant详解
- 即时通信 (广播)
- POJ 2349 Arctic Network (最小生成树第K大(小)边)
- 根据时间戳获取相应的日期和时间
- !HDU 5305 朋友关系网一半网友问题-dfs-(暴力搜索)
- try-except-else-finally
- 长篇专访科比:成功没秘诀 只有不断努力
- Java里this的作用和用法
- 第十三章 int 指令
- 黑马程序员---struts2学习笔记之五(文件上传)
- 黑马程序员---OC基础---Block、分类Category、协议protocol
- 【Windows编程】系列第八篇:通用对话框
- 【Windows编程】系列第八篇:通用对话框
- JAVA学习第十六天
- android应用:如何控制闪光灯