org.bytedeco
javacv-platform
1.5.5
由于整个依赖较大(约900M),以下为实际需要的依赖(不同的操作系统需要根据自己的操作系统进行适配),以下xml配置了properties及dependencies两个节点。
bytecode-sys配置根据运行系统可以自行变更为,以下部分系统值:
系统 | 值 |
windows64 | windows-x86_64 |
windows32 | windows-x86 |
arm64 | linux-arm64 |
x86_64 | linux-x86_64 |
mac | macosx-x86_64 |
linux-x86_64
org.bytedeco
ffmpeg
4.3.2-1.5.5
*
*
org.bytedeco
ffmpeg
${bytecode-sys}
4.3.2-1.5.5
*
*
org.bytedeco
javacv
1.5.5
*
*
org.bytedeco
javacpp
1.5.5
*
*
org.bytedeco
javacpp
${bytecode-sys}
1.5.5
*
*
FFmpegFrameGrabber通过grab方法可以获取视频信息,当frame不为空则正常;
但是该方法会导致阻塞,因此此处通过Future的get方法,设置一个超时时间,超时后返回false。
import com.hz.utils.CustomThreadPool;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.junit.jupiter.api.Test;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
public class RtmpCheckTest {
@Test
public void test01() {
try (CustomThreadPool pool = CustomThreadPool.initPool(1, 1, 1, "ceshi");) {
Future future = pool.submit(() -> {
String rtmpUrl = "rtmp://yourRtmpServer:1935/live/test";
FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(rtmpUrl);
try {
grabber.start();
Frame frame = grabber.grab();
boolean status = frame != null;
return status;
} catch (Exception e) {
return false;
} finally {
grabber.stop();
}
});
Boolean status = false;
try {
status = future.get(10, TimeUnit.SECONDS);
} catch (Exception e) {
System.out.println(e.getMessage());
}
System.out.println("视频状态:" + status);
}
}
}
package com.hz.utils;
import java.io.Closeable;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @description:
* @author: pp_lan
* @date: 2022/3/15
*/
public class CustomThreadPool implements Closeable {
private ThreadPoolExecutor pool;
private AtomicInteger count = new AtomicInteger();
private CustomThreadPool(int core, int max, int queueSize, String threadName) {
this.pool = new ThreadPoolExecutor(core, max, 3, TimeUnit.SECONDS, new ArrayBlockingQueue<>(queueSize),
r -> new Thread(r, threadName + count.getAndIncrement()));
}
public ThreadPoolExecutor getPool() {
return pool;
}
/**
* 获取对象
* @param core
* @param max
* @param queueSize
* @param threadName
* @return
*/
public static CustomThreadPool initPool(int core, int max, int queueSize, String threadName) {
return new CustomThreadPool(core, max, queueSize, threadName);
}
/**
* callable批量任务
* @param tasks
* @param
* @return
*/
public List> invokeAll(Collection extends Callable> tasks) {
try {
List> futures = this.pool.invokeAll(tasks);
return futures;
} catch (InterruptedException e) {
throw new RuntimeException("线程被中断", e);
}
}
/**
* callable单个任务
* @param task
* @param
* @return
*/
public Future submit(Callable task) {
return this.pool.submit(task);
}
/**
* runnable任务
* @param runnable
*/
public void execute(Runnable runnable) {
this.pool.execute(runnable);
}
/**
* runnable任务
* @param runnable
*/
public Future> submit(Runnable runnable) {
return this.pool.submit(runnable);
}
/**
* 线程池关闭,建议使用try-resource进行自动关闭,不要手动执行
*/
public void shutdown() {
this.pool.shutdown();
try {
if (!this.pool.awaitTermination(1, TimeUnit.MINUTES)) {
this.pool.shutdownNow();
if (!this.pool.awaitTermination(1, TimeUnit.MINUTES)) {
throw new RuntimeException("线程池关闭失败");
}
}
} catch (InterruptedException e) {
throw new RuntimeException("线程池关闭失败", e);
}
}
@Override
public void close() {
this.shutdown();
}
}
RTSP环境搭建