天天看點

如何讀取H264并用RTP發送(VsParserSendH264)

在上一篇博文中介紹了一個H264檔案的解析封裝類(https://blog.csdn.net/toshiba689/article/details/86747620),而這篇博文給大家介紹怎麼把讀出來的H264資料以RTP協定發送出去。我繼續以前面讀H264的代碼為例子,加上發送H264的功能。

這個例子的main函數代碼如下:

int _tmain(int argc, _TCHAR* argv[])
{
	CFrameExtractFilter fileParser;

	fileParser.SetLoopMode(FALSE);
	if(fileParser.OpenFile(_T("D:\\videos\\185.1080P.264"), H264_DEC) != 0)
	{
		printf(("OpenFile failed \n"));
		return -1;
	}

	unsigned int current_timestamp = 0; //目前時間戳
	unsigned int timestamp_increase= 3600; //時間戳增量,90000/25 = 3600
    unsigned int frame_duration = 1000/25; //幀的間隔時間 

	unsigned char * pFrameBuffer = (unsigned char*)malloc(1000*1024);
    unsigned int nFrameSize = 0;
	char cType = '\0';

	// Init WinSock
	WSADATA   data;
	int ret = WSAStartup(0x0202, &data);
	if (ret != 0)
	{
		return -2;
	}

	H264Handler * pH264Handler = new H264Handler();
	pH264Handler->SetPayloadType(96);

	RTSPStream     StreamSender(10);
	StreamSender.InitUDPSocket(56120, "127.0.0.1", 1234);

	while(1)
	{
		nFrameSize = 0;
		if(fileParser.GetNextFrame(pFrameBuffer, &nFrameSize, &cType) <= 0) //擷取每一幀的資料内容,資料長度,幀類型(I/P/B)
		{
			break;
		}
		printf(("GetNextFrame got size: %d, frame_type: %c \n"), nFrameSize, cType);

	   //StreamSender.SendFrame(pFrameBuffer, nFrameSize, 96, current_timestamp);
		pH264Handler->WriteData(pFrameBuffer, nFrameSize, current_timestamp, &StreamSender);

		current_timestamp += timestamp_increase;

		Sleep(frame_duration);
	}

	free(pFrameBuffer);
    delete pH264Handler;

	WSACleanup();

	return 0;
}
           

跟之前的例子不同,這裡多定義了兩個變量:一個是H264Hander類型的指針變量pH264Handler,另外一個是RTSPStream類型的變量StreamSender。前者是負責将H264的幀切分成NALU單元,然後再以FU-A的打包格式把NALU封裝到RTP包裡;後者是用來發送RTP包的,隻支援UDP發送。RTPStream類型的對象在初始化時需要設定接收端的IP位址、目标端口号以及本地綁定的端口資訊(這個端口可以随意設定,隻要沒有被其他程序占用)。

H264Handler * pH264Handler = new H264Handler();
	pH264Handler->SetPayloadType(96);

	RTSPStream     StreamSender(10);
	StreamSender.InitUDPSocket(56120, "127.0.0.1", 1234);
           

然後,通過調用GetNextFrame獲得一個幀的資料,注意這個幀是不能馬上打包成RTP發送的,因為它不是一個NALU,按照H264的規範,需要以NALU為機關切分,然後再封裝到RTP包裡,一個NALU可以封裝到一個或多個RTP包裡面。前面說了,切分NALU和打包RTP都是由H264Handler類來處理,而實際上是由H264Handler::WriteData函數來處理,該函數内部組成RTP包,并且發送包到目标的IP位址。調用WriteData的示例代碼如下:

pH264Handler->WriteData(pFrameBuffer, nFrameSize, current_timestamp, &StreamSender);
           

傳給這個函數的參數除了幀的Buffer位址,幀的大小,RTSPStream類型的執行個體指針,還有時間戳。其中時間戳是一個32位的無符号整型,發送一幀後時間值會遞增,增加多少呢?這個是根據流的時鐘頻率和幀率來确定的,一般H264流的時鐘頻率是90000,我們可以了解為将1秒分成90000份,而機關時間就是1/90000秒。如果1秒有25幀,那麼每一個幀的Duration Time就有90000/25=3600,是以每次處理完一幀都将時間戳加上3600。

好了,介紹到這裡,其他大家看代碼吧!

代碼下載下傳位址:https://download.csdn.net/download/toshiba689/10948166

繼續閱讀