在VS2005下使用Jrtplib传送H263视频(using OpenCV2.2)

         终于捣鼓出点东西了!高兴啊~~~哈哈哈哈,首先感谢网络上的资源的帮助。

         1、RFC3550,3551,2190--ENU,http://www.faqs.org/rfcs/rfc3551.html

         2、CodeProject上的VideoNet:http://www.codeproject.com/KB/IP/videonet.aspx

         3、RFC3550--CHS,http://www.rosoo.net/a/201001/8356.html

         4、CSDN以及Rosoo上的关于时间戳的讲解;

               CSDN: http://blog.csdn.net/ldd909/article/details/6183439

               Rosoo:http://www.rosoo.net/a/201102/10965.html

        5、关于RTP的协议分析:http://blog.csdn.net/bripengandre/article/details/2238818

        6、关于H.263介绍:http://blog.csdn.net/menuconfig/article/details/2649041

        7、百度百科的RTP/RTCP的词条介绍:http://baike.baidu.com/view/1149098.html。

下面是程序的main源文件,需要的配置是VS2005+opencv2.2+jrtplib+h.263的编解码,所有的库文件等在压缩包中都有,整个工程的下载:http://download.csdn.net/source/3497956

main源码如下:是在前面几篇文章的基础上修改整合而成,仅用作测试

#include "header_rtph263.h"

using namespace jrtplib;

#ifdef SERVER
#undef SERVER
#endif

#define SERVER		//if defined than as a sender, else as a receiver

#ifdef SERVER
#define PORT_BASE	8000
#define DEST_PORT	2000
#else
#define PORT_BASE	2000
#define DEST_PORT	3000
#endif

//#define CAMERA	//if defined open default camera by opencv, else read from avi files

int ByteCount = 0;
unsigned char cdata[20000];
int cbuffer_size = 20000;
unsigned char rgbdata[400000];
int buffersize = 400000;

//编码回调
void OwnWriteFunction(int byte)
{
	if(ByteCount<cbuffer_size)
	{
		cdata[ByteCount]=(unsigned char)byte;
		++ByteCount;
	}
}

void checkerror(int rtperr)
{
	if (rtperr < 0)
	{
		std::cout << "ERROR: " << RTPGetErrorString(rtperr) << std::endl;
		exit(-1);
	}
}

int main(int argc, char **argv)
{
	//opencv var
	Mat frame;
	Mat temp[3];
	VideoCapture capture;
	int frameCount = 0;

	//h263 ----------encoder/decoder init
	uchar *readData = NULL;
	uchar *imgBuffer = NULL;

	unsigned int yuv[WIDTH*HEIGHT*3/2];
	CParam h263Param;
	Bits bits;
	InitLookupTable();
	h263Param.format = PARAM_FORM;
	InitH263Encoder(&h263Param);
	WriteByteFunction = OwnWriteFunction;
	InitH263Decoder();

	//rtp---initialze and creation
	WSADATA dat;
	WSAStartup(MAKEWORD(2,2), &dat);
	
	const size_t MaxPackSize = 20000;
	RTPSession session;
	RTPSessionParams sessionparams;
	sessionparams.SetOwnTimestampUnit(1.0/90000.0);	//for video ---see RFC2190

	RTPUDPv4TransmissionParams transparams;
	transparams.SetPortbase(PORT_BASE);

	int status = session.Create(sessionparams,&transparams);
	checkerror(status);

	uint8_t localip[]={127, 0, 0, 1};
	RTPIPv4Address addr(localip, DEST_PORT);
	status = session.AddDestination(addr);
	checkerror(status);

	session.SetDefaultPayloadType(34);	//PT for H.263----see RFC2190
	session.SetDefaultMark(true);		//true or false ?? both ok for my test	
	session.SetDefaultTimestampIncrement(3600);	// =90000/25
	session.SetMaximumPacketSize(MaxPackSize);
	
#ifdef SERVER

#ifdef CAMERA
	capture.open(0);
#else
	capture.open("d:\\video\\petsc1.avi");
#endif
	
	if (!capture.isOpened())
	{
		cout<<"open video/camera failed!"<<endl;
		return -1;
	}
	capture>>frame;
	if (frame.empty())
	{
		cout<<"grab frame failed! exit...."<<endl;
		return -1;
	}
	namedWindow("raw", CV_WINDOW_AUTOSIZE);

	while (waitKey(40) != 27)	//25 fps
	{
		capture>>frame;
		if (frame.empty())
		{
			cout<<"grab frame failed! exit...."<<endl;
			return -1;
		}
		++frameCount;
		resize(frame, temp[0], cv::Size(WIDTH, HEIGHT));	//resize to CIF
		imshow("raw", temp[0]);

////---------------------------compress image frames-------------------------//	
		ConvertRGB2YUV(WIDTH, HEIGHT, temp[0].data, yuv);
		ByteCount = 0;
		h263Param.format = PARAM_FORM;
		h263Param.inter = CPARAM_INTRA;
		h263Param.Q_intra = 8;
		h263Param.data = yuv;
		CompressFrame(&h263Param, &bits);
		cout<<"compressed byte count is: "<<ByteCount<<endl;
///-------------------------------------------------------------------------//

		status = session.SendPacket(cdata, ByteCount);
		checkerror(status);

	}

#else
	namedWindow("got", CV_WINDOW_AUTOSIZE);
	int packetNum = 0;

	while(waitKey(40) != 27)	//25fps
	{
		session.BeginDataAccess();
		if (session.GotoFirstSourceWithData())
		{
			do 
			{
				RTPPacket *packet;
				while( (packet = session.GetNextPacket()) != NULL)
				{
					cout<<"packet count: "<<++packetNum<<endl;
					size_t dataLen = packet->GetPayloadLength();
					cout<<"payload length: "<<dataLen<<endl;
					readData = packet->GetPayloadData();
					imgBuffer = new uchar[dataLen];
					memcpy(imgBuffer, readData, dataLen);

///----------------------------decompress--------------------------//
					DecompressFrame(imgBuffer, dataLen, rgbdata, buffersize);
///----------------------------------------------------------------//

					Mat GotImg(HEIGHT, WIDTH, CV_8UC3, rgbdata);
					if(GotImg.empty())
					{
						cout<<"got image has no data, exiting...."<<endl;
						return -1;
					}
					imshow("got", GotImg);

					//release buffers and packet
					delete []imgBuffer;
					imgBuffer = NULL;
					session.DeletePacket(packet);
				}
				
			} while (session.GotoNextSourceWithData());
		}
		session.EndDataAccess();

	}
#endif
///////////////////////////////////////////////////////////////////
	
	//release resources
	cvDestroyAllWindows();
	ExitH263Decoder();
	ExitH263Encoder(&h263Param);

	RTPTime delay(5.0);
	session.BYEDestroy(delay, "trans over", 10);
	WSACleanup();

	return 0;
}


          经测试在本机收发正常,在实验室的两台机子上也成功收发。

      需要注意的是,整个程序由宏#define SERVER来控制是作为接受还是发送,定义了SERVER则程序作为发送方,否则作为接受方。如果是发送avi文件的话,可能需要转换一下格式,有些avi直接使用opencv打不开。

你可能感兴趣的:(image,server,video,byte,delay,avi)