刚刚编译出jrtplib库来,一切都不会,没接触过流媒体的东西,RTP的协议等等,不懂~~~于是先拿了简单的传输一张图像试试。 图像的部分采用opencv2.2.
发送端是在lib的example2的基础上添加修改的,接收是在lib的example3的基础上修改的,经测试可以传输图像-----------虽然被RTP中的各种参数搞得很头大,慢慢研究研究吧,最终是要发送H.263格式的。
发送端:----------rtpheader.h是自己写的,把大部分常用的jrtplib库中的头文件都包含进去了。
#include "rtplib/rtpheader.h" #include <stdlib.h> #include <iostream> #include <core.hpp> #include <highgui.hpp> using namespace jrtplib; #pragma comment(lib, "jrtplib_d.lib") #pragma comment(lib, "jthread_d.lib") #pragma comment(lib, "ws2_32.lib") #pragma comment(lib, "opencv_core220d.lib") #pragma comment(lib, "opencv_highgui220d.lib") using namespace cv; using namespace std; int main(void) { #ifdef WIN32 WSADATA dat; WSAStartup(MAKEWORD(2,2),&dat); #endif // WIN32 RTPSession session; RTPSessionParams sessionparams; sessionparams.SetOwnTimestampUnit(1.0/80.0); RTPUDPv4TransmissionParams transparams; transparams.SetPortbase(8000); int status = session.Create(sessionparams,&transparams); if (status < 0) { std::cerr << RTPGetErrorString(status) << std::endl; exit(-1); } uint8_t localip[]={127,0,0,1}; RTPIPv4Address addr(localip,2000); status = session.AddDestination(addr); if (status < 0) { std::cerr << RTPGetErrorString(status) << std::endl; exit(-1); } Mat img; img = imread("d:\\picture\\rtp.bmp", 0); if (img.empty()) { cout<<"load img failed!"<<endl; return -1; } namedWindow("wnd", CV_WINDOW_AUTOSIZE); while(waitKey(30) != 27) imshow("wnd", img); cvDestroyAllWindows(); cout<<"next....img depth is: "<<img.channels()<<endl; cout<<"total size is: "<<img.cols*img.rows*img.channels()<<endl; for(int i=0; i<10; ++i) cout<<(int)img.data[i]<<","; cout<<endl; session.SetDefaultPayloadType(96); session.SetDefaultMark(false); // session.SetDefaultTimestampIncrement(160); session.SetMaximumPacketSize(20000); session.SetDefaultTimestampIncrement(img.cols*img.rows*img.channels()); uint8_t silencebuffer[160]; for (int i = 0 ; i < 160 ; i++) silencebuffer[i] = i; RTPTime delay(1.0); RTPTime starttime = RTPTime::CurrentTime(); int num = 0; bool done = false; while (!done) { //status = session.SendPacket(silencebuffer,160); status = session.SendPacket(img.data, img.cols*img.rows*img.channels()); if (status < 0) { std::cerr << RTPGetErrorString(status) << std::endl; exit(-1); } cout<<"send img times :"<<++num<<endl; /* session.BeginDataAccess(); if (session.GotoFirstSource()) { do { RTPPacket *packet; while ((packet = session.GetNextPacket()) != 0) { std::cout << "Got packet with " << "extended sequence number " << packet->GetExtendedSequenceNumber() << " from SSRC " << packet->GetSSRC() << std::endl; session.DeletePacket(packet); } } while (session.GotoNextSource()); } session.EndDataAccess(); */ RTPTime::Wait(delay); RTPTime t = RTPTime::CurrentTime(); t -= starttime; if (t > RTPTime(10.0)) done = true; } delay = RTPTime(10.0); session.BYEDestroy(delay,"Time's up",9); system("pause"); #ifdef WIN32 WSACleanup(); #endif // WIN32 return 0; }
接收端:将接收的数据保存为图像-------直接显示时发现有问题,卡住了。
#include "rtplib/rtpheader.h" #ifndef WIN32 #include <netinet/in.h> #include <arpa/inet.h> #else #include <winsock2.h> #endif // WIN32 #include <stdlib.h> #include <stdio.h> #include <iostream> #include <string> #include <core.hpp> #include <highgui.hpp> #pragma comment(lib, "opencv_core220d.lib") #pragma comment(lib, "opencv_highgui220d.lib") using namespace cv; using namespace std; using namespace jrtplib; // // This function checks if there was a RTP error. If so, it displays an error // message and exists. // void checkerror(int rtperr) { if (rtperr < 0) { std::cout << "ERROR: " << RTPGetErrorString(rtperr) << std::endl; exit(-1); } } // // The new class routine // /* class MyRTPSession : public RTPSession { protected: void OnNewSource(RTPSourceData *dat) { if (dat->IsOwnSSRC()) return; uint32_t ip; uint16_t port; if (dat->GetRTPDataAddress() != 0) { const RTPIPv4Address *addr = (const RTPIPv4Address *)(dat->GetRTPDataAddress()); ip = addr->GetIP(); port = addr->GetPort(); } else if (dat->GetRTCPDataAddress() != 0) { const RTPIPv4Address *addr = (const RTPIPv4Address *)(dat->GetRTCPDataAddress()); ip = addr->GetIP(); port = addr->GetPort()-1; } else return; RTPIPv4Address dest(ip,port); AddDestination(dest); struct in_addr inaddr; inaddr.s_addr = htonl(ip); std::cout << "Adding destination " << std::string(inet_ntoa(inaddr)) << ":" << port << std::endl; } void OnBYEPacket(RTPSourceData *dat) { if (dat->IsOwnSSRC()) return; uint32_t ip; uint16_t port; if (dat->GetRTPDataAddress() != 0) { const RTPIPv4Address *addr = (const RTPIPv4Address *)(dat->GetRTPDataAddress()); ip = addr->GetIP(); port = addr->GetPort(); } else if (dat->GetRTCPDataAddress() != 0) { const RTPIPv4Address *addr = (const RTPIPv4Address *)(dat->GetRTCPDataAddress()); ip = addr->GetIP(); port = addr->GetPort()-1; } else return; RTPIPv4Address dest(ip,port); DeleteDestination(dest); struct in_addr inaddr; inaddr.s_addr = htonl(ip); std::cout << "Deleting destination " << std::string(inet_ntoa(inaddr)) << ":" << port << std::endl; } void OnRemoveSource(RTPSourceData *dat) { if (dat->IsOwnSSRC()) return; if (dat->ReceivedBYE()) return; uint32_t ip; uint16_t port; if (dat->GetRTPDataAddress() != 0) { const RTPIPv4Address *addr = (const RTPIPv4Address *)(dat->GetRTPDataAddress()); ip = addr->GetIP(); port = addr->GetPort(); } else if (dat->GetRTCPDataAddress() != 0) { const RTPIPv4Address *addr = (const RTPIPv4Address *)(dat->GetRTCPDataAddress()); ip = addr->GetIP(); port = addr->GetPort()-1; } else return; RTPIPv4Address dest(ip,port); DeleteDestination(dest); struct in_addr inaddr; inaddr.s_addr = htonl(ip); std::cout << "Deleting destination " << std::string(inet_ntoa(inaddr)) << ":" << port << std::endl; } }; */ // // The main routine // int main(void) { #ifdef WIN32 WSADATA dat; WSAStartup(MAKEWORD(2,2),&dat); #endif // WIN32 RTPSession sess; uint16_t portbase; std::string ipstr; int status,i,num; uint8_t *pBuffer; uint8_t *pPayloadData; uchar *imgbuf = NULL; uchar *packBuffer = NULL; // First, we'll ask for the necessary information std::cout << "Enter local portbase:" << std::endl; std::cin >> portbase; std::cout << std::endl; std::cout << std::endl; std::cout << "Number of seconds you wish to wait:" << std::endl; std::cin >> num; // Now, we'll create a RTP session, set the destination // and poll for incoming data. RTPUDPv4TransmissionParams transparams; RTPSessionParams sessparams; // IMPORTANT: The local timestamp unit MUST be set, otherwise // RTCP Sender Report info will be calculated wrong // In this case, we'll be just use 8000 samples per second. sessparams.SetOwnTimestampUnit(1.0/80.0); sessparams.SetAcceptOwnPackets(true); transparams.SetPortbase(portbase); sess.SetMaximumPacketSize(20000); status = sess.Create(sessparams,&transparams); checkerror(status); int packagenum = 0; // namedWindow("wnd", CV_WINDOW_AUTOSIZE); for (i = 1 ; i <= num ; i++) { sess.BeginDataAccess(); // check incoming packets if (sess.GotoFirstSourceWithData()) { cout<<"circle :"<<i<<endl; do { RTPPacket *pack; while ((pack = sess.GetNextPacket()) != NULL) { // You can examine the data here printf("Got packet num: %d!\n", packagenum++); size_t datalen = pack->GetPayloadLength(); cout<<"payload size :"<<datalen<<endl; /* pBuffer = new uint8_t[datalen]; pPayloadData = (uint8_t *)pack->GetPayloadData(); memcpy(pBuffer, pPayloadData, datalen); std::cout<<"packet payload data is:"<<std::endl; for (int i=0; i<10; ++i) { std::cout<<(int)pBuffer[i]<<","; } std::cout<<std::endl; delete []pBuffer; pBuffer = NULL; */ packBuffer = (uchar *)pack->GetPayloadData(); imgbuf = new uchar[datalen]; memcpy(imgbuf, packBuffer, datalen); Mat img(107, 105, CV_8UC1, imgbuf); char name[20]; sprintf_s(name, 20, "img%d.bmp", packagenum); if(!img.empty()) { //imshow("wnd", img); imwrite(string(name), img); } else cout<<"received no data"<<endl; delete [] imgbuf; imgbuf = NULL; // we don't longer need the packet, so // we'll delete it sess.DeletePacket(pack); } } while (sess.GotoNextSourceWithData()); } sess.EndDataAccess(); #ifndef RTP_SUPPORT_THREAD status = sess.Poll(); checkerror(status); #endif // RTP_SUPPORT_THREAD RTPTime::Wait(RTPTime(1,0)); } sess.BYEDestroy(RTPTime(10,0),0,0); system("pause"); #ifdef WIN32 WSACleanup(); #endif // WIN32 return 0; }