JavaCV中FFmpegFrameGrabber调用start()方法时出现阻塞的解决办法

JvaCV中FFmpegFrameGrabber调用start方法阻塞的解决办法

项目码云(Gitee)地址:https://gitee.com/banmajio/RTSPtoRTMP
项目github地址:https://github.com/banmajio/RTSPtoRTMP
个人博客:banmajio’s blog

javacv使用ffmpeg将rtsp转rtmp直播流播放的问题解决与优化系列文章:
FFmpeg转封装rtsp到rtmp(无需转码,低资源消耗)
JavaCV中FFmpegFrameGrabber调用start()方法时出现阻塞的解决办法
JavaCV使用FFmpeg进行rtsp转rtmp直播流画面延时的优化方法
JavaCV1.5.3版本FFmpegFrameGrabber初始化的时候加载时间长的解决方法
av_write_frame() error -22 while writing video packet解决方法


问题描述

目前出现阻塞的情况有如下两种:
1.拉历史流的时候,会发生阻塞,grabber.start()阻塞无法继续执行。
2.如果rtsp指令的ip乱输(或者无法建立连接),start()也会发生阻塞。

解决方法


问题1

可以通过设置超时时间,如果拉不到流,触发超时时间,自动断开TCP连接。

		// 设置采集器构造超时时间(单位微秒,1秒=1000000微秒)
		grabber.setOption("stimeout", "2000000");

上述方法貌似没多大作用,依然会被阻塞…

查看源码发现会发生阻塞的函数有两个:

1.avformat_open_input():

打开流通道,探测一些视频格式等信息,对AVFormatContext结构体初始化。
对于这个函数阻塞的优化方法:将下面函数的seekCallback 设置为null,禁止javacv查找。

		avio = avio_alloc_context(new BytePointer(av_malloc(4096)), 4096, 0, oc, readCallback, null,
					maximumSize > 0 ? seekCallback : null);
2.avformat_find_stream_info():

探测流信息(宽高码率等信息)
这个函数存在执行时间较长或者阻塞的问题,可以通过以下属性设置,来减小函数执行的时间。probesize属性限制探测时读取的最大数据量。max_analyze_duration属性限制info函数执行的时长,AV_TIME_BASE是单位秒。但是对于阻塞的问题好像并不能有效的解决,只是可以缩短函数的执行时间:

		// 限制avformat_find_stream_info接口内部读取的最大数据量
		oc.probesize(5120);
		// 设置avformat_find_stream_info这个函数的持续时长,超过这个时间不结束也会结束
		oc.max_analyze_duration(5 * AV_TIME_BASE);
		// 将avformat_find_stream_info内部读取的数据包不放入AVFormatContext的缓冲区packet_buffer中
		oc.flags(AVFormatContext.AVFMT_FLAG_NOBUFFER);

3.使用inputstream进行推流时,最新版本的javacv(1.5.3),在grabber new的时候有一行注释:

/**
	 * Calls {@code FFmpegFrameGrabber(inputStream, Integer.MAX_VALUE - 8)} so that
	 * the whole input stream is seekable.
	 */
	public FFmpegFrameGrabber(InputStream inputStream) {
		this(inputStream, Integer.MAX_VALUE - 8);
	}

	/** Set maximumSize to 0 to disable seek and minimize startup time. */
	//将maximumSize设置为0以禁用查找并最小化启动时间
	public FFmpegFrameGrabber(InputStream inputStream, int maximumSize) {
		this.inputStream = inputStream;
		this.closeInputStream = true;
		this.pixelFormat = AV_PIX_FMT_NONE;
		this.sampleFormat = AV_SAMPLE_FMT_NONE;
		this.maximumSize = maximumSize;
	}

将maximumSize设置为0以禁用查找并最小化启动时间;也就是grabber = new FFmpegFrameGrabber(inputStream,0);效果等同于上述序号1的设置,不修改源码来禁用avio_alloc_context()函数的seekCallback

问题2

上述设置超时时间的方法对于拉流地址(rtsp指令中的ip)输入错误时并不生效,依旧会阻塞,查看源码奈何才疏学浅不知道如何解决。变向通过检测是否能建立TCP连接,来判定是否可以正常推拉流。

如下代码:如果可以建立连接,则继续执行;否则释放资源,return null;


		// 解决ip输入错误时,grabber.start();出现阻塞无法释放grabber而导致后续推流无法进行;
		Socket rtspSocket = new Socket();
		Socket rtmpSocket = new Socket();
		// 建立TCP Scoket连接,超时时间1s,如果成功继续执行,否则return
		try {
			rtspSocket.connect(new InetSocketAddress(cameraPojo.getIp(), 554), 1000);
		} catch (IOException e) {
			grabber.stop();
			grabber.close();
			rtspSocket.close();
			System.err.println("与拉流地址建立连接失败...");
			return null;
		}

		try {
			rtmpSocket.connect(new InetSocketAddress(IpUtil.IpConvert(config.getPush_ip()),
					Integer.parseInt(config.getPush_port())), 1000);
		} catch (IOException e) {
			grabber.stop();
			grabber.close();
			rtspSocket.close();
			System.err.println("与推流地址建立连接失败...");
			return null;
		}

如有错误或者更好的解决办法,请指正!!!

  • 7
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 47
    评论
注:下文的 *** 代表文件名的版本号。 # 【javacv-***.jar文文档.zip】 包含: 文文档:【javacv-***-javadoc-API文档-文(简体)版.zip】 jar包下载地址:【javacv-***.jar下载地址(官方地址+国内镜像地址).txt】 Maven依赖:【javacv-***.jar Maven依赖信息(可用于项目pom.xml).txt】 Gradle依赖:【javacv-***.jar Gradle依赖信息(可用于项目build.gradle).txt】 源代码下载地址:【javacv-***-sources.jar下载地址(官方地址+国内镜像地址).txt】 # 本文件关键字: javacv-***.jar文文档.zip,java,javacv-***.jar,org.bytedeco,javacv,***,cl.eye,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,bytedeco,文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压 【javacv-***.jar文文档.zip】,再解压其的 【javacv-***-javadoc-API文档-文(简体)版.zip】,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件; # Maven依赖: ``` <dependency> <groupId>org.bytedeco</groupId> <artifactId>javacv</artifactId> <version>***</version> </dependency> ``` # Gradle依赖: ``` Gradle: implementation group: 'org.bytedeco', name: 'javacv', version: '***' Gradle (Short): implementation 'org.bytedeco:javacv:***' Gradle (Kotlin): implementation("org.bytedeco:javacv:***") ``` # 含有的 Java package(包): ``` cl.eye org.bytedeco.javacv ``` # 含有的 Java class(类)(此处仅列举3个): ``` cl.eye.CLCamera org.bytedeco.javacv.AndroidFrameConverter org.bytedeco.javacv.BaseChildSettings ...... ```
注:下文的 *** 代表文件名的版本号。 # 【javacv-***.jar文文档.zip】 包含: 文文档:【javacv-***-javadoc-API文档-文(简体)版.zip】 jar包下载地址:【javacv-***.jar下载地址(官方地址+国内镜像地址).txt】 Maven依赖:【javacv-***.jar Maven依赖信息(可用于项目pom.xml).txt】 Gradle依赖:【javacv-***.jar Gradle依赖信息(可用于项目build.gradle).txt】 源代码下载地址:【javacv-***-sources.jar下载地址(官方地址+国内镜像地址).txt】 # 本文件关键字: javacv-***.jar文文档.zip,java,javacv-***.jar,org.bytedeco,javacv,***,cl.eye,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,bytedeco,文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压 【javacv-***.jar文文档.zip】,再解压其的 【javacv-***-javadoc-API文档-文(简体)版.zip】,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件; # Maven依赖: ``` <dependency> <groupId>org.bytedeco</groupId> <artifactId>javacv</artifactId> <version>***</version> </dependency> ``` # Gradle依赖: ``` Gradle: implementation group: 'org.bytedeco', name: 'javacv', version: '***' Gradle (Short): implementation 'org.bytedeco:javacv:***' Gradle (Kotlin): implementation("org.bytedeco:javacv:***") ``` # 含有的 Java package(包): ``` cl.eye org.bytedeco.javacv ``` # 含有的 Java class(类)(此处仅列举3个): ``` cl.eye.CLCamera org.bytedeco.javacv.AndroidFrameConverter org.bytedeco.javacv.BaseChildSettings ...... ```
注:下文的 *** 代表文件名的版本号。 # 【javacv-***.jar文文档.zip】 包含: 文文档:【javacv-***-javadoc-API文档-文(简体)版.zip】 jar包下载地址:【javacv-***.jar下载地址(官方地址+国内镜像地址).txt】 Maven依赖:【javacv-***.jar Maven依赖信息(可用于项目pom.xml).txt】 Gradle依赖:【javacv-***.jar Gradle依赖信息(可用于项目build.gradle).txt】 源代码下载地址:【javacv-***-sources.jar下载地址(官方地址+国内镜像地址).txt】 # 本文件关键字: javacv-***.jar文文档.zip,java,javacv-***.jar,org.bytedeco,javacv,***,cl.eye,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,bytedeco,文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压 【javacv-***.jar文文档.zip】,再解压其的 【javacv-***-javadoc-API文档-文(简体)版.zip】,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件; # Maven依赖: ``` <dependency> <groupId>org.bytedeco</groupId> <artifactId>javacv</artifactId> <version>***</version> </dependency> ``` # Gradle依赖: ``` Gradle: implementation group: 'org.bytedeco', name: 'javacv', version: '***' Gradle (Short): implementation 'org.bytedeco:javacv:***' Gradle (Kotlin): implementation("org.bytedeco:javacv:***") ``` # 含有的 Java package(包): ``` cl.eye org.bytedeco.javacv ``` # 含有的 Java class(类)(此处仅列举3个): ``` cl.eye.CLCamera org.bytedeco.javacv.AndroidFrameConverter org.bytedeco.javacv.BaseChildSettings ...... ```
注:下文的 *** 代表文件名的版本号。 # 【javacv-***.jar文文档.zip】 包含: 文文档:【javacv-***-javadoc-API文档-文(简体)版.zip】 jar包下载地址:【javacv-***.jar下载地址(官方地址+国内镜像地址).txt】 Maven依赖:【javacv-***.jar Maven依赖信息(可用于项目pom.xml).txt】 Gradle依赖:【javacv-***.jar Gradle依赖信息(可用于项目build.gradle).txt】 源代码下载地址:【javacv-***-sources.jar下载地址(官方地址+国内镜像地址).txt】 # 本文件关键字: javacv-***.jar文文档.zip,java,javacv-***.jar,org.bytedeco,javacv,***,cl.eye,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,bytedeco,文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压 【javacv-***.jar文文档.zip】,再解压其的 【javacv-***-javadoc-API文档-文(简体)版.zip】,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件; # Maven依赖: ``` <dependency> <groupId>org.bytedeco</groupId> <artifactId>javacv</artifactId> <version>***</version> </dependency> ``` # Gradle依赖: ``` Gradle: implementation group: 'org.bytedeco', name: 'javacv', version: '***' Gradle (Short): implementation 'org.bytedeco:javacv:***' Gradle (Kotlin): implementation("org.bytedeco:javacv:***") ``` # 含有的 Java package(包): ``` cl.eye org.bytedeco.javacv ``` # 含有的 Java class(类)(此处仅列举3个): ``` cl.eye.CLCamera org.bytedeco.javacv.AndroidFrameConverter org.bytedeco.javacv.BaseChildSettings ...... ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 47
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

banmajio

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值