TS流如何经过RTP封装及其vlc通过打开sdp文件的方式接收

头文件hTs.h:

/* Project by qiuliangbin copyright 2015-2018*/
/* Just for learning;                        */
/* Function:Use Rtp Transmition send Ts to VLC Media player*/

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>

#include <winsock2.h>
#include <winsock2.h>


#define PACKET_BUFFER_END            (unsigned int)0x00000000

#define DEST_IP                "10.1.1.124"
#define DEST_PORT            1234
#define MP2T                    33

typedef struct 
{
    /**//* byte 0 */
	/*数据源的个数(即源的个数),如果只有一个源那么此时的值为0*/
    unsigned char csrc_len:4;        /**//* expect 0 */
	/*扩充位,如果设置为允许的话,固定头结构后面(即包的12个字节后面,有效负载的前面)紧跟着一个扩展头结构,该结构是已定义的一种格式*/
    unsigned char extension:1;        /**//* expect 1, see RTP_OP below */
    /*是否填充,如果设置为允许填充的话,在包的末尾填充一个或多个字节,这些填充的字节不是有效负载的一部分。*/
	unsigned char padding:1;        /**//* expect 0 */
	/*RTP版本号*/
    unsigned char version:2;        /**//* expect 2 */
    /**//* byte 1 */
	/*有效负载,RTP数据的有效负载(不包括头12个字节),由具体的应用程序来确定负载的格式和意义。官方文档里有表格说明,该表格显示了格式代码和具体格式的对应关系,附加的格式代码可能不在RTP协议里定义。*/
    unsigned char payload:7;        /**//* RTP_PAYLOAD_RTSP */
	/*标识,在文档中是这样定义的,它有意标识重要的事物比如:在流媒体中标识一帧数据的边界(结束或开始)*/
    unsigned char marker:1;        /**//* expect 1 */
    /**//* bytes 2, 3 */
	/*数据包序号,发送的RTP数据包序号,接收端可用它来检查丢失的数据包和确定保存数据包次序*/
    unsigned short seq_no;            
    /**//* bytes 4-7 */
	/*时间戳, 纪录了RTP数据包中第一个字节的采样时间,采样时间必须源自一个时间增量且允许同步和计算*/
    unsigned  long timestamp;        
    /**//* bytes 8-11 */
	/*同步标识, 是一个随机数,在同一个RTP会话中只有一个同步标识。*/
    unsigned long ssrc;            /**//* stream number is used here. */
} RTP_FIXED_HEADER;

BOOL InitWinsock();

源文件hTs.cpp

// TsDecoder.cpp : Defines the entry point for the console application.
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>
#include "hTs.h"

FILE *bits = NULL;                //!< the bit stream file
FILE *bitsout = NULL;
#define PACKET_SIZE 188
#define GIVE_UP 1024
#define MTU 1590
int max_size = 800000;
int count = 0;
char buffer[200000] = {0};

RTP_FIXED_HEADER        *rtp_hdr;



void OpenBitstreamFile (char *fn)
{
	if (NULL == (bits=fopen(fn, "rb")))
	{
		printf("open file error\n");
		exit(0);
	}
}
void OpenBitstreamoutFile (char *fn)
{
	if (NULL == (bitsout=fopen(fn, "wb")))
	{
		printf("open out file error\n");
		exit(0);
	}
}
BOOL InitWinsock()
{
    int Error;
    WORD VersionRequested;
    WSADATA WsaData;
    VersionRequested=MAKEWORD(2,2);
    Error=WSAStartup(VersionRequested,&WsaData); //启动WinSock2
    if(Error!=0)
    {
        return FALSE;
    }
    else
    {
        if(LOBYTE(WsaData.wVersion)!=2||HIBYTE(WsaData.wHighVersion)!=2)
        {
            WSACleanup();
            return FALSE;
        }
        
    }
    return TRUE;
}


int GetAnnexbTS()
{	
	int n = 0;
	int FrameNum = 0;
	unsigned char *Buf;

	if ((Buf = (unsigned char*)calloc (max_size , sizeof(char))) == NULL) 
	  printf ("GetAnnexbNALU: Could not allocate Buf memory\n");

	/* Sync */
	while (1) 
	{
		if (1 != fread (Buf, 1, 1, bits))//从码流中读3个字节
		{
			free(Buf);
			return 0;
		}
		if(Buf[0] == 0x47)
		{
			int ncount =0;
			if ((n=fread(&Buf[1],1,PACKET_SIZE-1,bits)) == 187)
			{
				int readonebit = fgetc(bits);
				if ( readonebit== 0x47) 
				{
					FrameNum ++;
					if (0 != fseek (bits, -1 , SEEK_CUR))//把文件指针向后退开始字节的字节数
					{
						free(Buf);
						printf("GetAnnexbNALU: Cannot fseek in the bit stream file");
					}
					break;
				}
				if(readonebit == feof(bits))
				{
					//Frame 1~6 表示文件传输
				//	FrameNum = 0;//表示文件传输结束 
					return -1; //到文件末尾了
				}
				else
				{
					return -2;//忽略这一帧,在文件中有帧被破坏不需要对他做特别处理,直接存储
				}
			}    
				
		}
	}
	memcpy (buffer, &Buf[0],188);
	free(Buf);
	return FrameNum;
}

int main(int argc, char* argv[])
{
	int Ts_RetVal=0;
	int Fmno = 0;
	int	bytes=0;
	int position=0;
	unsigned short seq_num =0;
	OpenBitstreamFile("./222.ts");
	OpenBitstreamoutFile("./666666.ts");
	char sendbuf[1500];

	InitWinsock(); //初始化套接字库
	SOCKET    socket1;
	struct sockaddr_in server;
    int len =sizeof(server);
	float framerate=30;
	unsigned int timestamp_increse=0,ts_current=0;
	timestamp_increse=(unsigned int)(90000.0 / framerate); //+0.5);

	server.sin_family=AF_INET;
    server.sin_port=htons(DEST_PORT);          
    server.sin_addr.s_addr=inet_addr(DEST_IP); 
    socket1=socket(AF_INET,SOCK_DGRAM,0);
    connect(socket1, (const sockaddr *)&server, len) ;//申请UDP套接字
	int count = 0 ;

	memset(sendbuf,0,1500);
	while(!feof(bits)) {
		if ((Ts_RetVal=GetAnnexbTS()) == -1)
		{
			break;
		}
		Fmno += Ts_RetVal;
		memcpy(&sendbuf[12+(Fmno-1)*188],buffer,188);

		position = position + 188;
//		fwrite(&sendbuf[12+(Fmno-1)*188],1,PACKET_SIZE,bitsout);
		if ((Fmno == 7)&&(position >= 188*7))
		{			
			rtp_hdr =(RTP_FIXED_HEADER*)&sendbuf[0];
			//设置RTP HEADER,
			rtp_hdr->payload     = MP2T;  //负载类型号,
			rtp_hdr->version     = 2;  //版本号,此版本固定为2
			rtp_hdr->marker    = 0;   //标志位,由具体协议规定其值。
			rtp_hdr->ssrc        = htonl(10);    //随机指定为10,并且在本RTP会话中全局唯一
			rtp_hdr->marker=1;
			rtp_hdr->seq_no     = htons(seq_num ++); //序列号,每发送一个RTP包增1
			ts_current=ts_current+timestamp_increse;
			rtp_hdr->timestamp=htonl(ts_current);

			bytes=7*188 + 12 ;
			send( socket1, sendbuf, bytes, 0 );//发送rtp包
			fwrite(&sendbuf[12],1,7*188,bitsout);
			position = 0;
			Fmno = 0;
			memset(sendbuf,0,1500);
		}	
	//	dump(buffer,Fmno);	
	}

	if((position>0)&&(Fmno>0))//发最后一帧
	{
	//	memset(sendbuf,0,1500);
		rtp_hdr =(RTP_FIXED_HEADER*)&sendbuf[0];

		//设置RTP HEADER,
		rtp_hdr->payload     = MP2T;  //负载类型号,
		rtp_hdr->version     = 2;  //版本号,此版本固定为2
		rtp_hdr->marker    = 0;   //标志位,由具体协议规定其值。
		rtp_hdr->ssrc        = htonl(10);    //随机指定为10,并且在本RTP会话中全局唯一

		rtp_hdr->marker=1;
		rtp_hdr->seq_no     = htons(seq_num ++); //序列号,每发送一个RTP包增1

		int icount = 0;

//		memcpy(&sendbuf[12],buffer,188);

		ts_current=ts_current+timestamp_increse;

		rtp_hdr->timestamp=htonl(ts_current);
		bytes=188*Fmno+ 12 ;
		
		send( socket1, sendbuf, bytes, 0 );//发送rtp包	
		fwrite(&sendbuf[12],1,188*Fmno,bitsout);
	}
//	free(buffer);
	fclose(bits);
	fclose(bitsout);
	return 0;
}

SDP文件ts.sdp:

v=2
t=0 0 
m=video 9400 RTP/AVP 33  
a=rtpmap:33 MP2T
a=framerate:30
c=IN IP4 10.1.1.124

这些都经过本人亲测,有不懂可以提问,如果转载请注明出处。联系方式:13016390335@163.com

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值