刚刚编译出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;
}