海康sdk捕获码流数据通过JavaCV推成rtmp流的实现思路(PS流转封装RTMP)

本文转自javaCV社区群管理员:斑马jio的博客https://blog.csdn.net/weixin_40777510,感谢大佬倾情贡献,支持javacv社区发展壮大!

有关海康sdk对接和监控视频转流都可以参考斑马jio的博客。再次对大佬表示感谢!

 

海康sdk捕获码流数据通过JavaCV推成rtmp流的实现思路(PS流转封装RTMP)

 

码云(Gitee)主页:https://gitee.com/banmajio
github主页:https://github.com/banmajio
个人博客:banmajio’s blog

海康sdk二次开发系列文章
海康sdk捕获码流数据通过JavaCV推成rtmp流的实现思路(PS流转封装RTMP)
海康sdk进行历史回放时,码流数据回调过快问题的解决方法
海康sdk项目(java)部署Linux环境相关问题总结
海康sdk部署Linux环境下无法播放子码流的问题
海康sdk项目部署Linux系统时出现java.lang.UnstisfiedLinkError:jnidispatch(xxx)not found in resource path错误

浏览器不支持flash插件之后,h5播放rtmp直播流的解决方案

【注意】:对于直播来说,可以采用rtsp-rtmp这种方案来实现。但是对于历史回放功能,采用rtsp指令带starttime和endtime参数来进行回放时,因为nvr带宽限制,会出现带宽不足的错误。所以目前没有想到更好的解决方案。故采用海康sdk二次开发,捕获到直播流或者历史流数据,自己转封装推成rtmp。

现项目已经开发完成,主要功能如下:
1.实时预览
2.历史回放
3.断线重连
4.关闭视频流
5.断线续播
6.等若干bug问题
具体功能可参考RtspToRtmp的项目,功能基本一致,但是通过sdk解决了历史回放的问题
https://gitee.com/banmajio/RTSPtoRTMP
增加了部署到Linux环境下的解决方案,服务性能也已通过测试。
考虑到开发成本,暂不准备开源,有需要demo的请加Q:1402325991 联系!

问题分析

通过海康sdk注册回调函数,可以捕获到视频的码流数据。但是因为海康sdk回调的码流数据是ps封装的h264的码流数据,也就是说通过海康sdk可以得到视频的ps流

转码推rtmp

最开始的时候,找到一个demo,是将海康sdk回调函数中将码流数据的byte[]—>BytePointer—>Mat,然后又通过opencv_imgproc.cvtColor()将yv12的Mat转为rgb的Mat,接着将rgb的Mat转为了Frame帧,最后通过FFmpegFrameRecorder.record(Frame)将帧推送到rtmp地址上。虽然这种方式可以实现我们的需求,但是带来的问题是,cpu占用率极高。大概推三路cpu就占满了。查看JavaCV源码发现FFmpegFrameRecorder.record(Frame)方法会对帧进行编解码的动作,然后将Frame转换为AVPacket。CPU高的原因也正是消耗在了编解码的地方。

	this.bPointer = new BytePointer(frameBean.getBuffer().length);
	this.yv12Mat = new Mat(height + height / 2, width, CV_8UC1);
	this.rgbMat = new Mat(height, width, CV_8UC3);
	if (this.converter == null) {
		this.converter = new ToIplImage();
	}
	if (this.matConverter == null) {
		this.matConverter = new ToMat();
	}
	// 图像转码-----↓
	// 填充指针
	this.bPointer.put(frameBean.getBuffer());
	// mat填充
	this.yv12Mat.data(this.bPointer);
	// 转码opencv实现方式
	opencv_imgproc.cvtColor(this.yv12Mat, this.rgbMat, opencv_imgproc.COLOR_YUV2BGR_YV12);
	// 转换为帧
	this.matFrame = this.matConverter.convert(this.rgbMat);
	// 图像转码-----↑
	try {
		this.recorder.record(this.matFrame);
	} catch (Exception e) {
		e.printStackTrace();
	}

PS流转封装

后来在一个技术交流群内了解到,Javacv是可以将PS流转封装为flv格式推到rtmp的。具体的实现思路就是通过Java的管道流,将sdk回调函数中获得的码流数据写入PipedOutputStream中,然后将对应的PipedInputStream当做参数传入到FFmpegFrameGrabber的构造方法中。其余的操作和拉rtsp流推rtmp流大体类似。可以参考JavaCV转封装rtsp到rtmp(无需转码,低资源消耗)
其中要注意的几点就是:
1.管道流PipedInputStream,PipedOutputStream不可以在同一线程下使用否则会造成死锁。
2.管道流是一种阻塞流,PipedOutputStream.write(byte[])会将数据放到PipedInputStream的缓冲区中,当PipedInputStream将这部分数据read()出去后,PipedOutputStream才会继续write。这个缓冲区的大小默认值时1024。也可以自己手动通过下面的这种方式指定缓冲区大小。

	PipedInputStream inputStream = new PipedInputStream(5120);
  • 1

3.管道流PipedInputStream,PipedOutputStream成对出现,需要将两者建立连接才能正常工作。建立连接有以下两种方式:

	//第一种方式
	PipedInputStream inputStream = new PipedInputStream();
	PipedOutputStream outputStream = new PipedOutputStream(inputStream);

	//第二种方式
	PipedInputStream inputStream = new PipedInputStream();
	PipedOutputStream outputStream = new PipedOutputStream();
	inputStream.connect(outputStream);

4.推流方式和rtsp推流方式几乎相同

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 博客之星2020 设计师:CY__0809 返回首页
实付 9.90元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值