低延时高RTSP兼容的EasyPlayer-RTSP-win解决H.264一帧多个nal单元录像花屏问题方案

EasyPlayer-RTSP-win解决H264一帧多个nal单元录像花屏问题

我们来讲解一下关于H264编码格式中的一帧多nal(Network Abstract Layer, 即网络抽象层),关于H264和NAL,这里引用一段话来科普一下:

【转】 在H.264/AVC视频编码标准中,整个系统框架被分为了两个层面:视频编码层面(VCL)和网络抽象层面(NAL)。其中,前者负责有效表示视频数据的内容,而后者则负责格式化数据并提供头信息,以保证数据适合各种信道和存储介质上的传输。因此我们平时的每帧数据就是一个NAL单元(SPS与PPS除外)。在实际的H264数据帧中,往往帧前面带有00 00 00 01 或 00 00 01分隔符,一般来说编码器编出的首帧数据为PPS与SPS,接着为I帧……

一般情况下,一个H264帧直接以00 00 00 01开头作为一个NAL作为网络传输单元,而在有些H264的编码器则编码出来的H264帧包含了多个NAL,这个时候每个分片的NAL(注意是分片的)则是是以00 00 01开头作为网络传输单元,经过分片的NAL数据量更小,从而更加方便进行网络;但是,我们在接收到带有多个NAL的H264帧的时候进行写MP4则不能简单是只通过将头部的00 00 00 01标志转换从AVC的长度标识,而需要将所有的00 00 00 01和00 00 01都需要转换成该NAL单元的长度,否则就会出现视频解码只能播放头部一小部分,其他部分全部花屏的情况,如下图所示:

说了这么多,大家是否明白了呢,如果不明白的(文字描述比较虚),我们直接看EasyPlayer代码实现:

int EasyMP4Writer::WriteMp4File(unsigned char* pdata, int datasize, bool keyframe, long nTimestamp, int nWidth, int nHeight)
{
	if (nTimestamp==0||(pdata==NULL)||datasize<=0)
	{
		return -1;
	}
	int inlen=datasize;
	unsigned char*pin=pdata;
	int outlen=0;
	unsigned char*pout=NULL;
	bool bend = false;

	int datalen=0;
	bool bSPSOrPPS = false;

	int iOutLen = datasize;

	unsigned char* pRealData = new unsigned char[datasize<<1];
	int nRealDataSize = 0;
	memset(pRealData,0x00, datasize+4);
	do
	{
		int nal_start = 0;
		int nal_end = 0;
		outlen = find_nal_unit(pin,inlen, &nal_start, &nal_end );
		if (outlen<=0)
		{
			break;
		}
		pout = pin+nal_start;
		if(pout!=NULL)
		{
			unsigned char naltype = ( pout[0] & 0x1F);

			if (naltype==0x07)//0x67
			{
// 				m_psps=pout;
// 				m_spslen=outlen;
				//pout[0] = 0x67;
				if(m_bwritevideoinfo==false)
				{
					m_psps = new unsigned char[outlen];
					memcpy(m_psps, pout, outlen);
					m_spslen=outlen;
				}
				bSPSOrPPS = true;
			}
			else if (naltype==0x08)//0x68
			{
				// 				m_ppps=pout;
				// 				m_ppslen=outlen;
				//pout[0] = 0x68;
				if(m_bwritevideoinfo==false)
				{
					m_ppps = new unsigned char[outlen];//outlen
					memcpy(m_ppps, pout, outlen);
					m_ppslen = outlen;
				}
				bSPSOrPPS = true;
			}
// 			else if (pout[0] == 0x06)//SEI
// 			{
//
// 			}
//			else
			{
				memcpy(pRealData+nRealDataSize, &outlen, 4);
				//写入头4个字节==nal内容的长度(H264数据的长度)
				unsigned char byte0 = pRealData[nRealDataSize+3];
				unsigned char byte1 = pRealData[nRealDataSize+2];
				pRealData[nRealDataSize+3] = pRealData[nRealDataSize+0];
				pRealData[nRealDataSize+2] = pRealData[nRealDataSize+1];
				pRealData[nRealDataSize+1] = byte1;
				pRealData[nRealDataSize+0] = byte0;

				nRealDataSize += 4;

				memcpy(pRealData+nRealDataSize, pout, outlen);
				nRealDataSize += outlen;
			}

			inlen=inlen-outlen-(pout-pin);
			pin=pout+outlen;
		}
	} while (bend!=true);

	if (m_bwritevideoinfo==false&&m_ppps&&m_psps)
	{
		// PPS末尾的0过滤,否则VLC可能播放不出来 [12/22/2015 Dingshuai]
		int nPPSSize = m_ppslen;
		int nZeroCount = 0;
		for (int nI = nPPSSize-1; nI>=0; nI--)
		{
			if (m_ppps[nI] == 0x00)
			{
				nZeroCount++;
			}
			else
			{
				break;
			}
		}
		m_ppslen = m_ppslen-nZeroCount;
		WriteH264SPSandPPS(m_psps,m_spslen,m_ppps,m_ppslen,nWidth,nHeight);
		m_bwritevideoinfo = true;
	}
	if (m_bwritevideoinfo==false||nRealDataSize<=0 )
	{
		return 0;//获取sps pps失败
	}

// 	if(/*bSPSOrPPS*/pout[0]==0x67 || pout[0]==0x68)
// 	{
// 		return 0;
// 	}
	WriteH264Frame(pRealData, nRealDataSize, keyframe, nTimestamp);//左移4单位,加上数据长度头?

	if (pRealData)
	{
		delete []pRealData;
		pRealData = NULL;
	}

	return true;
}

其中find_nal_unit()函数是从H264帧中分析出以00 00 00 01和00 00 01开头的NAL单元,然后直接填充成该NAL单元的长度,注意字节顺序为大端顺序:
//写入头4个字节==nal内容的长度(H264数据的长度)

unsigned char byte0 = pRealData[nRealDataSize+3];
unsigned char byte1 = pRealData[nRealDataSize+2];
pRealData[nRealDataSize+3] = pRealData[nRealDataSize+0];
pRealData[nRealDataSize+2] = pRealData[nRealDataSize+1];
pRealData[nRealDataSize+1] = byte1;
pRealData[nRealDataSize+0] = byte0;

将NAL长度拷贝到AVC的缓冲区内,紧接着数据部分拷贝:
memcpy(pRealData+nRealDataSize, pout, outlen);
最后,组装成完成的avc帧之后写入MP4,播放的时候就不会有花屏、马赛克的情况出现了。

原文地址:https://www.cnblogs.com/TSINGSEE/p/11714029.html

时间: 2024-10-09 08:36:35

低延时高RTSP兼容的EasyPlayer-RTSP-win解决H.264一帧多个nal单元录像花屏问题方案的相关文章

HLS播放器RTSP播放器支持8K播放且低延时高并发全功能流媒体播放器EasyPlayer搭建之HTML中 px,em,rem该如何区别?

EasyPlayer是一款流媒体播放器系列项目,支持RTSP.RTMP.HTTP.HLS.UDP.RTP.File等多种流媒体协议播放. 支持本地文件播放,支持本地抓拍.本地录像.播放旋转.多屏播放.倍数播放等多种功能特性,核心基于ffmpeg,稳定.高效.可靠.可控. 随着多年不断的发展和迭代,不断基于成功的实践经验,发展出包括有: EasyPlayer-RTSP.EasyPlayer-RTMP.EasyPlayerPro 和EasyPlayer.js 等播放器.目前支持Windows. An

支持8K播放且低延时高并发全功能的流媒体播放器EasyPlayerPro如何播放H.265视频?

需求分析 一般对于一个播放器,应该支持如下几种显示模式: 等比例,最大化区域显示,不裁剪 等比例,最大区域显示,裁剪 拉伸显示,铺满全屏 要实现这几种显示模式.其实只要对播放控件的布局进行些许调整即可. 那EasyPlayer是怎么实现的呢?EasyPlayerPro是一款全功能的流媒体播放器,支持RTSP.RTMP.HTTP.HLS.UDP.RTP.File等多种流媒体协议播放.支持本地文件播放,支持本地抓拍.本地录像.播放旋转.多屏播放.倍数播放等多种功能特性,核心基于ffmpeg,稳定.高

提升linux 低延时 高吞吐量 性能的配置

一>修改句柄数 Ulimit –a 1)修改文件:/etc/security/limits.conf,在文件中添加:(立即生效-当前session中运行ulimit -a命令无法显示) 1.  * soft nofile 32768 #限制单个进程最大文件句柄数(到达此限制时系统报警) 2.  * hard nofile 65536 #限制单个进程最大文件句柄数(到达此限制时系统报错) * soft nofile 32768 * hard nofile 65536 2)修改文件:/etc/sys

海康大华摄像头高起播低延时RTSP网页无插件流媒体播放器EasyPlayer-RTSP-Win录像和抓图实现线程优化方案分享

EasyPlayer-RTSP播放器是一套RTSP专用的播放器,包括有:Windows(支持IE插件,npapi插件).Android.iOS三个平台,是由青犀TSINGSEE开放平台开发和维护的区别于市面上大部分的通用播放器,EasyPlayer-RTSP系列从2014年初发展至今得到了各行各业(尤其是安防行业)的广泛应用,其主要原因是EasyPlayer-RTSP更加精炼.更加专注,具备低延时和高RTSP协议兼容性. ? EasyPlayer-RTSP-Win录像和抓图实现线程优化 测试发现

低延时的RTMP网络直播

互联网时代的直播需求越来越多,观看直播的人群对直播的要求也越来越高.在百度或谷歌等搜索引擎里输入关键词"网络直播延时",大家的疑问不少: ü 什么软件看直播无延迟? ü 为什么网络直播与电视直播有大概2分钟的延迟? ü CCTV 的新闻直播是实时直播,还是做了延迟处理? ü 网络直播哪家好,没有延迟的? ü 为什么在网上看直播会比电视直播有几分钟的延迟? ü 大家如何看待关于网络直播延时的问题? ü 如何解决直播延迟? ü 视频直播时,你看到的是几秒以前的画面? ü 希望大家推荐一个延

H.264/ACC音视频编码流的RTP/RTSP传输实现(1)

目标: 实现一个用于H.264/ACC音视频编码流的RTP/RTSP传输的简单服务器,主要通过此过程学习基于RTP的NAL.ADTS码流封装技术和基于RTSP的视频交互控制技术.完整系统应该包括服务器和客户端两个部分,其中服务器负责接收客户端请求.封包以及发送音视频数据,客户端负责发送请求和接收视频数据.分别在Windows平台上和Android平台上进行网络传输实体测试,通过客户端网络流抓包和播放器播放对系统进行进一步验证. 简介: 随着互联网和移动通信的飞速发展,H.264凭借其突出的编码效

干货:如何实现RTSP推送H.264、RTSP推送H.265(hevc)

rtsp推送相关的资料和测试软件比较少,本文介绍rtsp推送相关信令和测试效果: 1. rtsp推送流程. 主要分两部分:第一部分先发送信令:第二部分发送rtp包. ?信令流程: ?1.1?先发送OPTIONS, OPTIONS比较常用,就不做详细说明了. 1.2 发送ANNOUNCE, 发送ANNOUNCE主要是把要推送的音视频信息通过sdp格式传给服务器.关于sdp信息如何构造,对于h264请参考rfc6184. h265请参考rfc7798. 下面举两个例子. h264+aac ANNOU

分析一下H5直播、微信直播、抓娃娃、低延时的方案

微信直播,HTML5直播,主要方案有如下几种: 1,基于hls切片直播,前前是应用的主流,服务器可以选fms,wowza,nginx,srs之类 优点:集成方便,支持度高,兼容性好,主流手都支持,是目前直播技术主流. 缺点:延时大,一般服务器可以控制切片时长(延时可以控制在15-30秒之间) 2,基于浏览器mse技术,目前端技术上有B站的flv解码器.后端技术srs之类. 优点:集成方便,兼容性一般,原有技术平台可以保留,延时可以控制在10秒内 缺点:(主要是部分浏览器不支持mse,),目前IO

阿里云李刚:下一代低延时的直播CDN

摘要: 在上周落幕帷幕的多媒体领域技术盛会--LiveVideoStackCon音视频技术大会上,阿里云的高级技术专家李刚进行了<下一代低延时的直播CDN>技术分享.主讲人李刚,多年关注在CDN这个领域,早期主要研究和cache服务器缓存以及流媒体相关的技术, 专注CDN文件分发.图片与大文件下载等业务. 在上周落幕帷幕的多媒体领域技术盛会--LiveVideoStackCon音视频技术大会上,阿里云的高级技术专家李刚进行了<下一代低延时的直播CDN>技术分享.主讲人李刚,多年关注