ps流提取H264并解码播放

本文介绍了如何从海康的PS流中提取H264数据,并进行解码播放。针对视频编解码新手,详细讲解了接收RTP流、解析PS流(包括海康私有格式)以及解码播放H264流的三个步骤。虽然过程中遇到丢包导致的花屏问题,但提供了参考资源和实现方案。
摘要由CSDN通过智能技术生成

因为需要从海康ps流中提取H264数据并进行解码播放,才有了这篇文章.因为是视频编解码领域的纯入门新手,个别理解或者方法有误,需要自行判断,不过相关方法已经测试通过,对于
像我这样的新手还是有一定的借鉴的.断断续续搞了很长一段时间,把相关经验分享给各个新手.

---------------------------------------------------------------------------------------------------------

分为3个部分来说吧,仅供参考.
1. 接收并且解析RTP流部分
2. 解析ps流部分,包括解析海康部分私有格式
3. 将提取的标准H264流进行解码播放

--------------------------------------------------------------------------------------------------------

接收并且解析RTP流:

当时想到了两种方案:1.编写udp-socket来接受流,然后自己解析rtp包. 2.使用jrtplib库来接受流,自动解析rtp包. 由于第二种方案简单易用,使用了第二种方案.实验过程发现jrtplib会
出现丢包的情况,导致花屏的出现.具体丢包原因未查明.(jrtplib使用了最简单的框架,摘自jrtplib的其中一个example,未精简,未使用thread,效果还可以)

//该函数主要作用是使用jrtplib接收rtp流,并且解析出H264,将一帧帧的H264存入一个deque中
DWORD WINAPI GetSocketData(LPVOID lpparentet) 
{
	//jrtplib的相关初始化
	WSADATA dat;
	WSAStartup(MAKEWORD(2,2),&dat);
	RTPSession session;
	RTPSessionParams sessionparams;
	sessionparams.SetOwnTimestampUnit(1.0/3600.0);
	sessionparams.SetUsePollThread(true);
	RTPUDPv4TransmissionParams transparams;
	transparams.SetPortbase(6000);
	session.SetMaximumPacketSize(sessionparams.GetMaximumPacketSize()+1000);
	transparams.SetRTPReceiveBuffer(transparams.GetRTCPReceiveBuffer()*3);
	transparams.SetRTCPReceiveBuffer(transparams.GetRTCPReceiveBuffer()*3);
	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,9000);
	status = session.AddDestination(addr);
	if (status < 0)
	{
		std::cerr << RTPGetErrorString(status) << std::endl;
		exit(-1);
	}
	session.SetDefaultPayloadType(96);
	session.SetDefaultMark(false);
	session.SetDefaultTimestampIncrement(160);
	uint8_t silencebuffer[160];
	for (int i = 0 ; i < 160 ; i++)
		silencebuffer[i] = 128;
	RTPTime delay(0.02);
	RTPTime starttime = RTPTime::CurrentTime();
	/收到rtp包之后进行数据处理
	bool full=true;
	bool done = false;
	int i=0;
	while (!done)
	{
		session.BeginDataAccess();
		if (session.GotoFirstSource())
		{
			do
			{
				RTPPacket *packet;
				while ((packet = session.GetNextPacket()) != 0)
				{
					//查找ps头 0x000001BA
					if (packet->GetPacketData()[12]==0x00 && packet->GetPacketData()[13]==0x00 && packet->GetPacketData()[14]==0x01 && packet->GetPacketData()[15]==0xba)
					{
						if (i!=0)
						{
							//此包为ps新的一帧,每次到这里都先处理存储好的前一帧
							int iPsLength=0;
							GetH246FromPs(jimbak,jimlen,&returnps,&iPsLength); //从ps流中提取h264
							//海康流特殊处理部分:分界符数据(nal_unit_type=9)或补充增强信息单元(nal_unit_type=6),如果直接送入解码器,有可能会出现问题,直接舍弃.00 00 01 bd和 00 00 01 c0为私有标志和
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值