http://blog.csdn.net/liushu1231/article/details/9203593 [cpp] view plaincopy jrtp传输: 好了,下面是我写的使用jrtp进行发送h264数据包的例子,具体解释可以看注释。发送端也可以接收接收端发送过来的rtcp数据包。 #define win32 #define debug #defin
http://blog.csdn.net/liushu1231/article/details/9203593
[cpp] view plaincopy
jrtp传输: 好了,下面是我写的使用jrtp进行发送h264数据包的例子,具体解释可以看注释。发送端也可以接收接收端发送过来的rtcp数据包。 #define win32
#define debug
#define max_rtp_pkt_length 1360
#define h264 96
#include rtpsession.h
#include rtpudpv4transmitter.h
#include rtpipv4address.h
#include rtpsessionparams.h
#include rtperrors.h
#include rtcpapppacket.h
#ifndef win32
#include
#include
#else
#include
#endif // win32
#include
#include
#include
#include
#include
extern c
{
#include x264.h
#include x264_config.h
};
using namespace jrtplib;
using namespace std; bool checkerror(int rtperr); class crtpsender : public rtpsession { public: crtpsender(void); ~crtpsender(void); protected: void onapppacket(rtcpapppacket *apppacket,const rtptime &receivetime,const rtpaddress *senderaddress); void onbyepacket(rtpsourcedata *srcdat); void onbyetimeout(rtpsourcedata *srcdat); public: void sendh264nalu(unsigned char* m_h264buf,int buflen); void setparamsforsendingh264(); }; bool checkerror(int rtperr) { if (rtperr { std::couterror: return false; } return true; } crtpsender::crtpsender(void) { } crtpsender::~crtpsender(void) { } void crtpsender::onapppacket(rtcpapppacket *apppacket,const rtptime &receivetime,const rtpaddress *senderaddress) {//收到rtcp app数据 std::coutgot rtcp packet from: std::coutgot rtcp subtype: getsubtype() std::coutgot rtcp data: char *)apppacket->getappdata() return ; } void crtpsender::sendh264nalu(unsigned char* m_h264buf,int buflen) { unsigned char *psendbuf; //发送数据指针 psendbuf = m_h264buf; //去除前导码0x000001 或者0x00000001 //if( 0x01 == m_h264buf[2] ) //{ // psendbuf = &m_h264buf[3]; // buflen -= 3; //} //else //{ // psendbuf = &m_h264buf[4]; // buflen -= 4; //} char sendbuf[1430]; //发送的数据缓冲 memset(sendbuf,0,1430); int status; printf(send packet length %d \n,buflen); if ( buflen { memcpy(sendbuf,psendbuf,buflen); status = this->sendpacket((void *)sendbuf,buflen); checkerror(status); } else if(buflen > max_rtp_pkt_length) { //设置标志位mark为0 this->setdefaultmark(false); //printf(buflen = %d\n,buflen); //得到该需要用多少长度为max_rtp_pkt_length字节的rtp包来发送 int k=0,l=0; k = buflen / max_rtp_pkt_length; l = buflen % max_rtp_pkt_length; int t=0;//用指示当前发送的是第几个分片rtp包 char nalheader = psendbuf[0]; // nalu 头a?¤ while( t 0 ) ) { if( (0 == t ) || ( t//第一包到最后包的前一包 { /*sendbuf[0] = (nalheader & 0x60)|28; sendbuf[1] = (nalheader & 0x1f); if ( 0 == t ) { sendbuf[1] |= 0x80; } memcpy(sendbuf+2,&psendbuf[t*max_rtp_pkt_length],max_rtp_pkt_length); status = this->sendpacket((void *)sendbuf,max_rtp_pkt_length+2);*/ memcpy(sendbuf,&psendbuf[t*max_rtp_pkt_length],max_rtp_pkt_length); status = this->sendpacket((void *)sendbuf,max_rtp_pkt_length); checkerror(status); t++; } //最后一包 else if( ( k==t && l>0 ) || ( t== (k-1) && l==0 )) { //设置标志位mark为1 this->setdefaultmark(true); int isendlen; if ( l > 0) { isendlen = buflen - t*max_rtp_pkt_length; } else isendlen = max_rtp_pkt_length; //sendbuf[0] = (nalheader & 0x60)|28; //sendbuf[1] = (nalheader & 0x1f); //sendbuf[1] |= 0x40; //memcpy(sendbuf+2,&psendbuf[t*max_rtp_pkt_length],isendlen); //status = this->sendpacket((void *)sendbuf,isendlen+2); memcpy(sendbuf,&psendbuf[t*max_rtp_pkt_length],isendlen); status = this->sendpacket((void *)sendbuf,isendlen); checkerror(status); t++; } } } } void crtpsender::setparamsforsendingh264() { this->setdefaultpayloadtype(h264);//设置传输类型 this->setdefaultmark(true); //设置位 this->settimestampunit(1.0/9000.0); //设置采样间隔 this->setdefaulttimestampincrement(3600);//设置时间戳增加间隔 } void crtpsender::onbyepacket(rtpsourcedata *srcdat) { } void crtpsender::onbyetimeout(rtpsourcedata *srcdat) { } #define ssrc 100 #define dest_ip_str 192.168.1.252 #define dest_port 1234 #define base_port 2222 #include rtpsender.h
int inal = 0; x264_nal_t* pnals = null; void setrtpparams(crtpsender& sess,uint32_t destip,uint16_t destport,uint16_t baseport) { int status; //rtp+rtcp库初始化socket环境 rtpudpv4transmissionparams transparams; rtpsessionparams sessparams; sessparams.setowntimestampunit(1.0/9000.0); //时间戳单位 sessparams.setacceptownpackets(true); //接收自己发送的数据包 sessparams.setusepredefinedssrc(true); //设置使用预先定义的ssrc sessparams.setpredefinedssrc(ssrc); //定义ssrc transparams.setportbase(baseport); status = sess.create(sessparams,&transparams); checkerror(status); destip = ntohl(destip); rtpipv4address addr(destip,destport); status = sess.adddestination(addr); checkerror(status); //为发送h264包设置参数 //sess.setparamsforsendingh264(); } bool initsocket() { int error; word versionrequested; wsadata wsadata; versionrequested=makeword(2,2); error=wsastartup(versionrequested,&wsadata); //启动winsock2 if(error!=0) { printf(error:start winsock failed!\n); return false; } else { if(lobyte(wsadata.wversion)!=2||hibyte(wsadata.whighversion)!=2) { printf(error:the version is winsock2!\n); wsacleanup(); return false; } } return true; } void closesocket(crtpsender sess) { //发送一个bye包离开会话最多等待秒钟超时则不发送 sess.byedestroy(rtptime(3,0),0,0); wsacleanup(); } int main(int argc, char** argv) { initsocket(); crtpsender sender; string destip_str = 127.0.0.1; uint32_t dest_ip = inet_addr(destip_str.c_str()); setrtpparams(sender,dest_ip,dest_port,base_port); sender.setparamsforsendingh264(); //…x264设置参数等步骤,具体参见上篇博客 for(int i = 0; i { //读取一帧 read_frame_y4m(ppicin,(hnd_t*)y4m_hnd,i); if( i ==0 ) ppicin->i_pts = i; else ppicin->i_pts = i - 1; //编码 int frame_size = x264_encoder_encode(px264handle,&pnals,&inal,ppicin,ppicout); if(frame_size >0) { for (int i = 0; i {//将编码数据写入文件t //fwrite(pnals[i].p_payload, 1, pnals[i].i_payload, pfile); //发送编码文件 sender.sendh264nalu(pnals[i].p_payload,pnals[i].i_payload); rtptime::wait(rtptime(1,0)); } } } closesocket(sender); //一些清理工作… }