1.实时视频流解决方案
目录
1.实时视频流解决方案
2.步骤
1.搭建rtmp+flv服务器
3.实时预览
1.配置海康sdk库文件
2.修改FPREVIEW_NEWLINK_CB代码,推流
3.修改FPREVIEW_DATA_CB代码,取流
4.javacv的推流
3.部分代码
1.启动项目初始化cms,stream的代码
2.cms代码
3.stream代码
1.前端调用后台接口,
2.后台接口调用海康sdk开启具体的摄像头监听,获取摄像头实时流数据
3.建立管道,海康sdk监听线程和javacv推流线程共享管道
4.sdk线程向管道输出流写数据,javacv推流线程向rtmp发送管道数据。即sdk生产者,javacv是消费者
5.nginx+rtmp+flv模块接收到视频流,可以通过http的路径在浏览器访问
前端->后台->海康sdk—>管道->javacv->nginx+rtmp+flv->http路径
2.步骤
1.搭建rtmp+flv服务器
windows系统下,自己编译比较麻烦,这边有大佬编译好的windows中obs+nginx-http-flv-module的流媒体服务搭建_windows nginx集成http-flv_OneCodeSolvesAll的博客-CSDN博客个人编译好的:链接:https://pan.baidu.***/s/1XKkyYvK5W6yZA1w2mPaAfg
提取码:3ug6
linux环境下,下载nginx-http-flv-module(包含nginx-rtmp-module),添加到nginx重载配置就行,网上有很多教程。
如果不需要flv,也可以单独下载nginx-rtmp-module,添加到nginx重载配置。
2.java预览demo
1.登录海康平台海康开放平台
选择硬件产品的isup sdk下载
2.解压之后
java的这个demo直接打开,修改一下nvr信息,包括ip端口就可以直接预览。
3.实时预览
1.配置海康sdk库文件
海康文档lib文件夹下的文件就是库文件,JavaISUPDemo\lib下也有,需要注意文档是win还是linux版本的。
2.修改FPREVIEW_NEWLINK_CB代码,推流
每当***_ECMS_StartGetRealStreamV11,开启预览时,FPREVIEW_NEWLINK_CB便会监听到预览请求。
创建管道,分别用于取流推流。异步开始调用javacv的推流方法。
PipedInputStream pis = new PipedInputStream();
PipedOutputStream pos = new PipedOutputStream();
Stream.streamMap.put("stream:"+lLinkHandle,pos);
pos.connect(pis);
***pletableFuture.runAsync(()-> {
try {
PushUtil.grabAndPushRtmp(pis,"rtmp://"+rtmphost+"/live/"+userId+"_"+ dwChannelNo);
} catch (Exception e) {
e.printStackTrace();
}
}, Executors.newFixedThreadPool(1));
3.修改FPREVIEW_DATA_CB代码,取流
每当监听到视频流时,将视频流写入pos管道。注意此处不能使用redis,redis会严重影响此处代码性能,导致取流失败。每监听一次,是一个新的线程。第一块注释的代码是调试时使用,调试完之后要删掉。第二块注释代码pos也可以存到map中,使用时从map取,此处直接构造方法传进来也可以。
public class FPREVIEW_DATA_CB implements HCISUPStream.PREVIEW_DATA_CB {
private PipedOutputStream pos;
public FPREVIEW_DATA_CB(PipedOutputStream pos) {
this.pos = pos;
}
//实时流回调函数/
@Override
public void invoke(int iPreviewHandle, HCISUPStream.***_EHOME_PREVIEW_CB_MSG pPreviewCBMsg, Pointer pUserData) throws Exception {
// if (Count == 500) {//降低打印频率
// log.info("FPREVIEW_DATA_CB callback, iPreviewHandle:{}", iPreviewHandle);
// log.info("FPREVIEW_DATA_CB callback, data length:" + pPreviewCBMsg.dwDataLen);
// Count = 0;
// }
// Count++;
long offset = 0;
ByteBuffer buffers = pPreviewCBMsg.pRecvdata.getByteBuffer(offset, pPreviewCBMsg.dwDataLen);
byte[] bytes = new byte[pPreviewCBMsg.dwDataLen];
buffers.rewind();
buffers.get(bytes);
try{
//2.将数据读入到内存空间,此处不可用redis,否则执行时间是当前10倍
// PipedOutputStream pos = Stream.streamMap.get("stream:"+iPreviewHandle);
pos.write(bytes);
} catch (Exception e) {
e.printStackTrace();
}
}
}
4.javacv的推流
关于2.提到的javacv推流,linux和windows环境所需要的依赖包不同。
以下,test的是本地windows环境使用的,runtime是线上使用的,可不写,因为默认就是runtime。
<!-- Linux x86_64 使用 --> <dependency> <groupId>org.bytedeco</groupId> <artifactId>javacpp</artifactId> <version>1.5.7</version> </dependency> <dependency> <groupId>org.bytedeco</groupId> <artifactId>opencv</artifactId> <version>4.5.5-1.5.7</version> <classifier>linux-x86_64</classifier> <scope>runtime</scope> </dependency> <dependency> <groupId>org.bytedeco</groupId> <artifactId>openblas</artifactId> <version>0.3.19-1.5.7</version> <classifier>linux-x86_64</classifier> <scope>runtime</scope> </dependency> <dependency> <groupId>org.bytedeco</groupId> <artifactId>ffmpeg</artifactId> <version>5.0-1.5.7</version> <classifier>linux-x86_64</classifier> <scope>runtime</scope> </dependency> <!-- Windows x86_64 使用 --> <dependency> <groupId>org.bytedeco</groupId> <artifactId>opencv</artifactId> <version>4.5.5-1.5.7</version> <classifier>windows-x86_64</classifier> <scope>test</scope> </dependency> <dependency> <groupId>org.bytedeco</groupId> <artifactId>openblas</artifactId> <version>0.3.19-1.5.7</version> <classifier>windows-x86_64</classifier> <scope>test</scope> </dependency> <dependency> <groupId>org.bytedeco</groupId> <artifactId>ffmpeg</artifactId> <version>5.0-1.5.7</version> <classifier>windows-x86_64</classifier> <scope>test</scope> </dependency> <dependency> <groupId>org.bytedeco</groupId> <artifactId>javacv</artifactId> <version>1.5.7</version> <exclusions> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>*</artifactId> </exclusion> </exclusions> </dependency>
推流代码原理就是,javacv抓取帧,根据帧率算出间隔时间推送到rtmp服务器。
package ***.ei.ambulance.util.video;
import org.bytedeco.ffmpeg.avcodec.AVCodecParameters;
import org.bytedeco.ffmpeg.avformat.AVFormatContext;
import org.bytedeco.ffmpeg.avformat.AVStream;
import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.ffmpeg.global.avutil;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.FFmpegLogCallback;
import org.bytedeco.javacv.Frame;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.PipedInputStream;
/**
* @author willzhao
* @version 1.0
* @description 读取指定的mp4文件,推送到SRS服务器
* @date 2021/11/19 8:49
*/
public class PushUtil {
private static final Logger log = LoggerFactory.getLogger(PushUtil.class);
/**
* 推送到SRS服务器
*
* @param pis
* @param pushAddress 推流地址
* @throws Exception
*/
public static void grabAndPushRtmp(PipedInputStream pis, String pushAddress) throws Exception {
Thread.sleep(500);
// ffmepg日志级别
avutil.av_log_set_level(avutil.AV_LOG_ERROR);
FFmpegLogCallback.set();
// 实例化帧抓取器对象,将文件路径传入
// 1.直接以文件形式实例化帧抓取器,此方式可以推送h264,ps码流格式的MP4
// FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(MP4_FILE_PATH);
// 2.从文件中取流实例化帧抓取器,此方式只能推送ps码流的MP4
FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(pis,0);
long startTime = System.currentTimeMillis();
log.info("开始初始化帧抓取器");
// 下面两行设置可加可不加
grabber.setOption("analyzeduration", "1000000");
// grabber.setFormat("h264");
// 初始化帧抓取器,例如数据结构(时间戳、编码器上下文、帧对象等),
// 如果入参等于true,还会调用avformat_find_stream_info方法获取流的信息,放入AVFormatContext类型的成员变量oc中
grabber.start(true);
// grabber.startUnsafe(true); // 也可以使用此方法
log.info("帧抓取器初始化完成,耗时[{}]毫秒", System.currentTimeMillis()-startTime);
// grabber.start方法中,初始化的解码器信息存在放在grabber的成员变量oc中
AVFormatContext avFormatContext = grabber.getFormatContext();
// 文件内有几个媒体流(一般是视频流+音频流)
int streamNum = avFormatContext.nb_streams();
// 没有媒体流就不用继续了
if (streamNum<1) {
log.error("文件内不存在媒体流");
return;
}
// 取得视频的帧率
int frameRate = (int)grabber.getVideoFrameRate();
log.info("视频帧率[{}],视频时长[{}]秒,媒体流数量[{}]",
frameRate,
avFormatContext.duration()/1000000,
avFormatContext.nb_streams());
// 遍历每一个流,检查其类型
for (int i=0; i< streamNum; i++) {
AVStream avStream = avFormatContext.streams(i);
AVCodecParameters avCodecParameters = avStream.codecpar();
log.info("流的索引[{}],编码器类型[{}],编码器ID[{}]", i, avCodecParameters.codec_type(), avCodecParameters.codec_id());
}
// 视频宽度
int frameWidth = grabber.getImageWidth();
// 视频高度
int frameHeight = grabber.getImageHeight();
// 音频通道数量
int audioChannels = grabber.getAudioChannels();
log.info("视频宽度[{}],视频高度[{}],音频通道数[{}]",
frameWidth,
frameHeight,
audioChannels);
// 实例化FFmpegFrameRecorder,将SRS的推送地址传入
FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(pushAddress,
frameWidth,
frameHeight,
audioChannels);
// 设置编码格式
recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
// 设置封装格式
recorder.setFormat("flv");
// 一秒内的帧数
recorder.setFrameRate(frameRate);
// 两个关键帧之间的帧数
recorder.setGopSize(frameRate);
// 设置音频通道数,与视频源的通道数相等
recorder.setAudioChannels(grabber.getAudioChannels());
startTime = System.currentTimeMillis();
log.info("开始初始化帧抓取器");
// 初始化帧录制器,例如数据结构(音频流、视频流指针,编码器),
// 调用av_guess_format方法,确定视频输出时的封装方式,
// 媒体上下文对象的内存分配,
// 编码器的各项参数设置
recorder.start();
log.info("帧录制初始化完成,耗时[{}]毫秒", System.currentTimeMillis()-startTime);
Frame frame;
startTime = System.currentTimeMillis();
log.info("开始推流");
long videoTS = 0;
int videoFrameNum = 0;
int audioFrameNum = 0;
int dataFrameNum = 0;
// 假设一秒钟15帧,那么两帧间隔就是(1000/15)毫秒
int interVal = 1000/frameRate;
// 发送完一帧后sleep的时间,不能完全等于(1000/frameRate),不然会卡顿,
// 要更小一些,这里取八分之一
interVal/=8;
// 持续从视频源取帧
while (null!=(frame=grabber.grab())) {
videoTS = 1000 * (System.currentTimeMillis() - startTime);
// 时间戳
recorder.setTimestamp(videoTS);
// 有图像,就把视频帧加一
if (null!=frame.image) {
videoFrameNum++;
}
// 有声音,就把音频帧加一
if (null!=frame.samples) {
audioFrameNum++;
}
// 有数据,就把数据帧加一
if (null!=frame.data) {
dataFrameNum++;
}
// 取出的每一帧,都推送到SRS
recorder.record(frame);
// 停顿一下再推送
Thread.sleep(interVal);
}
log.info("推送完成,视频帧[{}],音频帧[{}],数据帧[{}],耗时[{}]秒",
videoFrameNum,
audioFrameNum,
dataFrameNum,
(System.currentTimeMillis()-startTime)/1000);
// 关闭帧录制器
recorder.close();
// 关闭帧抓取器
grabber.stop();
grabber.close();
pis.close();
}
}
其中,Thread.sleep(500);是必要的。要保证此线程执行到后面代码时,管道中必须存在流,这样开始初始化帧抓取器才能成功。即取流线程必须先于推流线程执行。否则会报错。
3.部分代码
代码中涉及到部分业务代码,按需修改。
1.启动项目初始化cms,stream的代码
package ***.ei.ambulance;
import ***.ei.ambulance.mapper.BreastpieceMapper;
import ***.ei.ambulance.mapper.BreastpieceVideoMapper;
import ***.ei.ambulance.mapper.TaskDetailMapper;
import ***.ei.ambulance.util.RedisUtil;
import ***.ei.ambulance.util.cacheMap.CacheMap;
import ***.ei.ambulance.util.isup.Cms;
import ***.ei.ambulance.util.isup.Stream;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.***mandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.***ponent;
/**
* @author zhangyd
* @date 2022/9/20
*/
@***ponent
@Slf4j
@Order(1)
public class ISUPIniter implements ***mandLineRunner {
@Value("${hik.cmsServerIP}")
String cmsServerIp;
@Value("${hik.cmsServerPort}")
String cmsServerPort;
@Value("${hik.voiceSmsServerIP}")
String voiceSmsServerIp;
@Value("${hik.voiceSmsServerPort}")
String voiceSmsServerPort;
@Value("${hik.breastpieceVideoPath}")
String breastpieceVideoPath;
@Value("${rtmp.rtmphost}")
private String rtmphost;
@Value("${hik.smsServerIP}")
String smsServerIP;
@Value("${hik.smsServerPort}")
String smsServerPort;
@Autowired
RedisUtil redisUtil;
@Autowired
BreastpieceMapper breastpieceMapper;
@Autowired
TaskDetailMapper taskDetailMapper;
@Autowired
BreastpieceVideoMapper breastpieceVideoMapper;
@Override
public void run(String... args) throws Exception {
Cms cms = new Cms();
cms.redisUtil = redisUtil;
cms.breastpieceMapper = breastpieceMapper;
cms.taskDetailMapper = taskDetailMapper;
cms.breastpieceVideoMapper = breastpieceVideoMapper;
cms.cMS_Init();
cms.startCmsListen(cmsServerIp, cmsServerPort, breastpieceVideoPath);
Stream stream = new Stream();
stream.eStream_Init();
stream.startRealPlayListen(smsServerIP, smsServerPort);
Stream.redisUtil = redisUtil;
Stream.rtmphost = rtmphost;
CacheMap.put("stream", stream);
CacheMap.put("cms", cms);
redisUtil.deletePattern("video:*");
}
}
2.cms代码
package ***.ei.ambulance.util.isup;
import ***.alibaba.fastjson.JSONArray;
import ***.alibaba.fastjson.JSONObject;
import ***.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import ***.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import ***.ei.ambulance.mapper.BreastpieceMapper;
import ***.ei.ambulance.mapper.BreastpieceVideoMapper;
import ***.ei.ambulance.mapper.TaskDetailMapper;
import ***.ei.ambulance.model.Breastpiece;
import ***.ei.ambulance.model.BreastpieceVideo;
import ***.ei.ambulance.model.ambulanceManage.TaskDetail;
import ***.ei.ambulance.util.RedisUtil;
import ***.ei.ambulance.util.Xml2JsonUtil;
import ***.ei.ambulance.util.cacheMap.CacheMap;
import ***.ei.ambulance.util.hik.OsSelect;
import ***.ei.ambulance.vo.video.VideoFileInfoVo;
import ***.ei.ambulance.vo.video.VideoFilesReq;
import ***.sun.istack.internal.NotNull;
import ***.sun.jna.Native;
import ***.sun.jna.Pointer;
import lombok.extern.slf4j.Slf4j;
import org.dom4j.DocumentException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @author zhangyd
* @date 2022/9/20
*/
@Slf4j
public class Cms {
public static Map<String,Integer> userLoginMap = new HashMap<>();
public RedisUtil redisUtil;
public BreastpieceMapper breastpieceMapper;
public TaskDetailMapper taskDetailMapper;
public BreastpieceVideoMapper breastpieceVideoMapper;
public static HCISUPCMS hCEhomeCMS = null;
//CMS监听句柄
public static int CmsHandle = -1;
//注册回调函数实现
static FRegisterCallBack fRegisterCallBack;
HCISUPCMS.***_EHOME_CMS_LISTEN_PARAM struCMSListenPara = new HCISUPCMS.***_EHOME_CMS_LISTEN_PARAM();
/**
* 根据不同操作系统选择不同的库文件和库路径
*
* @return
*/
private static boolean createSDKInstance() {
if (hCEhomeCMS == null) {
synchronized (HCISUPCMS.class) {
String strDllPath = "";
try {
if (OsSelect.isWindows()) {
//win系统加载库路径(路径不要带中文)
strDllPath = System.getProperty("user.dir") + "\\lib\\isupsdk\\HCISUPCMS.dll";
} else if (OsSelect.isLinux()) {
//Linux系统加载库路径(路径不要带中文)
strDllPath = System.getProperty("user.dir") + "/lib/isupsdkLinux/libHCISUPCMS.so";
log.info("===============1{}", strDllPath);
// strDllPath = "/usr/soft/java-service/ambulance/lib/isupsdkLinux/libHCISUPCMS.so";
}
hCEhomeCMS = (HCISUPCMS) Native.loadLibrary(strDllPath, HCISUPCMS.class);
} catch (Exception ex) {
log.info("loadLibrary: " + strDllPath + " Error: " + ex.getMessage());
return false;
}
}
}
return true;
}
/**
* cms服务初始化,开启监听
*
* @throws IOException
*/
public void cMS_Init() throws IOException {
if (hCEhomeCMS == null) {
if (!createSDKInstance()) {
log.info("Load CMS SDK fail");
return;
}
}
if (OsSelect.isWindows()) {
HCISUPCMS.BYTE_ARRAY ptrByteArrayCrypto = new HCISUPCMS.BYTE_ARRAY(256);
String strPathCrypto = System.getProperty("user.dir") + "\\lib\\isupsdk\\libeay32.dll"; //Linux版本是libcrypto.so库文件的路径
System.arraycopy(strPathCrypto.getBytes(), 0, ptrByteArrayCrypto.byValue, 0, strPathCrypto.length());
ptrByteArrayCrypto.write();
hCEhomeCMS.***_ECMS_SetSDKInitCfg(0, ptrByteArrayCrypto.getPointer());
//设置libssl.so所在路径
HCISUPCMS.BYTE_ARRAY ptrByteArraySsl = new HCISUPCMS.BYTE_ARRAY(256);
String strPathSsl = System.getProperty("user.dir") + "\\lib\\isupsdk\\ssleay32.dll"; //Linux版本是libssl.so库文件的路径
System.arraycopy(strPathSsl.getBytes(), 0, ptrByteArraySsl.byValue, 0, strPathSsl.length());
ptrByteArraySsl.write();
hCEhomeCMS.***_ECMS_SetSDKInitCfg(1, ptrByteArraySsl.getPointer());
//注册服务初始化
boolean binit = hCEhomeCMS.***_ECMS_Init();
//设置HCAapSDK***组件库文件夹所在路径
HCISUPCMS.BYTE_ARRAY ptrByteArray*** = new HCISUPCMS.BYTE_ARRAY(256);
String strPath*** = System.getProperty("user.dir") + "\\lib\\isupsdk\\HCAapSDK***"; //只支持绝对路径,建议使用英文路径
System.arraycopy(strPath***.getBytes(), 0, ptrByteArray***.byValue, 0, strPath***.length());
ptrByteArray***.write();
hCEhomeCMS.***_ECMS_SetSDKLocalCfg(5, ptrByteArray***.getPointer());
} else if (OsSelect.isLinux()) {
//todo linux版本的sdk
HCISUPCMS.BYTE_ARRAY ptrByteArrayCrypto = new HCISUPCMS.BYTE_ARRAY(256);
String strPathCrypto = System.getProperty("user.dir") + "/lib/isupsdkLinux/libcrypto.so"; //Linux版本是libcrypto.so库文件的路径
log.info("===============2{}", strPathCrypto);
System.arraycopy(strPathCrypto.getBytes(), 0, ptrByteArrayCrypto.byValue, 0, strPathCrypto.length());
ptrByteArrayCrypto.write();
hCEhomeCMS.***_ECMS_SetSDKInitCfg(0, ptrByteArrayCrypto.getPointer());
//设置libssl.so所在路径
HCISUPCMS.BYTE_ARRAY ptrByteArraySsl = new HCISUPCMS.BYTE_ARRAY(256);
String strPathSsl = System.getProperty("user.dir") + "/lib/isupsdkLinux/libssl.so"; //Linux版本是libssl.so库文件的路径
log.info("===============3{}", strPathSsl);
System.arraycopy(strPathSsl.getBytes(), 0, ptrByteArraySsl.byValue, 0, strPathSsl.length());
ptrByteArraySsl.write();
hCEhomeCMS.***_ECMS_SetSDKInitCfg(1, ptrByteArraySsl.getPointer());
//注册服务初始化
boolean binit = hCEhomeCMS.***_ECMS_Init();
//设置HCAapSDK***组件库文件夹所在路径
HCISUPCMS.BYTE_ARRAY ptrByteArray*** = new HCISUPCMS.BYTE_ARRAY(256);
String strPath*** = System.getProperty("user.dir") + "/lib/isupsdkLinux/HCAapSDK***/"; //只支持绝对路径,建议使用英文路径
log.info("===============4{}", strPath***);
System.arraycopy(strPath***.getBytes(), 0, ptrByteArray***.byValue, 0, strPath***.length());
ptrByteArray***.write();
hCEhomeCMS.***_ECMS_SetSDKLocalCfg(5, ptrByteArray***.getPointer());
}
hCEhomeCMS.***_ECMS_SetLogToFile(3, System.getProperty("user.dir") + "/EHomeSDKLog", false);
}
public void startCmsListen(String cmsServerIp, String cmsServerPort, String breastpieceVideoPath) {
if (fRegisterCallBack == null) {
fRegisterCallBack = new FRegisterCallBack();
fRegisterCallBack.ip = cmsServerIp;
fRegisterCallBack.port = "8007";
fRegisterCallBack.breastpieceVideoPath = breastpieceVideoPath;
}
System.arraycopy(cmsServerIp.getBytes(), 0, struCMSListenPara.struAddress.szIP, 0, cmsServerIp.length());
struCMSListenPara.struAddress.wPort = Short.parseShort(cmsServerPort);
struCMSListenPara.fnCB = fRegisterCallBack;
struCMSListenPara.write();
//启动监听,接收设备注册信息
CmsHandle = hCEhomeCMS.***_ECMS_StartListen(struCMSListenPara);
if (CmsHandle < -1) {
log.info("***_ECMS_StartListen failed, error code:" + hCEhomeCMS.***_ECMS_GetLastError());
hCEhomeCMS.***_ECMS_Fini();
return;
}
String cmsListenInfo = new String(struCMSListenPara.struAddress.szIP).trim() + "_" + struCMSListenPara.struAddress.wPort;
log.info("注册服务器:" + cmsListenInfo + ",***_ECMS_StartListen su***eed!\n");
}
public boolean setHeart(int lUserID, long dwKeepAliveSec, long dwTimeOutCount) {
boolean result = hCEhomeCMS.***_ECMS_SetAliveTimeout(lUserID, dwKeepAliveSec, dwTimeOutCount);
if (result) {
log.info("device ***_ECMS_SetAliveTimeout su***ess");
} else {
log.info("device ***_ECMS_SetAliveTimeout failed, error code: {}", hCEhomeCMS.***_ECMS_GetLastError());
}
return result;
}
public String channels(int channel, int lUserID) throws DocumentException {
HCISUPCMS.***_EHOME_PTXML_PARAM m_struParam = new HCISUPCMS.***_EHOME_PTXML_PARAM();
m_struParam.read();
String url = "GET /ISAPI/ContentMgmt/InputProxy/channels";
HCISUPCMS.BYTE_ARRAY ptrUrl = new HCISUPCMS.BYTE_ARRAY(1024);
System.arraycopy(url.getBytes(), 0, ptrUrl.byValue, 0, url.length());
ptrUrl.write();
m_struParam.pRequestUrl = ptrUrl.getPointer();
m_struParam.dwRequestUrlLen = url.length();
HCISUPCMS.BYTE_ARRAY ptrOutByte = new HCISUPCMS.BYTE_ARRAY(100 * 1024);
m_struParam.pOutBuffer = ptrOutByte.getPointer();
m_struParam.dwOutSize = 100 * 1024;
m_struParam.write();
if (!hCEhomeCMS.***_ECMS_ISAPIPassThrough(lUserID, m_struParam)) {
int iErr = hCEhomeCMS.***_ECMS_GetLastError();
log.info("***_ECMS_ISAPIPassThrough failed, error:{}", iErr);
m_struParam.read();
ptrOutByte.read();
log.info("ptrOutByte:{}", new String(ptrOutByte.byValue).trim());
}
String xml = new String(m_struParam.pOutBuffer.getByteArray(0, m_struParam.dwOutSize));
xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + xml;
JSONObject result = Xml2JsonUtil.xml2Json(xml);
JSONArray jsonArray = result.getJSONArray("inputproxychannel");
for (int i = 0; i < jsonArray.size(); i++) {
JSONObject j = jsonArray.getJSONObject(i);
if (j.getInteger("id") == channel) {
return j.getJSONObject("sourceinputportdescriptor").getString("ipaddress");
}
}
return null;
}
public List<Integer> cameraList(int lUserID) throws DocumentException {
HCISUPCMS.***_EHOME_PTXML_PARAM m_struParam = new HCISUPCMS.***_EHOME_PTXML_PARAM();
m_struParam.read();
String url = "GET /ISAPI/ContentMgmt/InputProxy/channels";
HCISUPCMS.BYTE_ARRAY ptrUrl = new HCISUPCMS.BYTE_ARRAY(1024);
System.arraycopy(url.getBytes(), 0, ptrUrl.byValue, 0, url.length());
ptrUrl.write();
m_struParam.pRequestUrl = ptrUrl.getPointer();
m_struParam.dwRequestUrlLen = url.length();
HCISUPCMS.BYTE_ARRAY ptrOutByte = new HCISUPCMS.BYTE_ARRAY(100 * 1024);
m_struParam.pOutBuffer = ptrOutByte.getPointer();
m_struParam.dwOutSize = 100 * 1024;
m_struParam.write();
if (!hCEhomeCMS.***_ECMS_ISAPIPassThrough(lUserID, m_struParam)) {
int iErr = hCEhomeCMS.***_ECMS_GetLastError();
log.info("***_ECMS_ISAPIPassThrough failed, error:{}", iErr);
m_struParam.read();
ptrOutByte.read();
log.info("ptrOutByte:{}", new String(ptrOutByte.byValue).trim());
}
String xml = new String(m_struParam.pOutBuffer.getByteArray(0, m_struParam.dwOutSize));
xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + xml;
JSONObject resultJson = Xml2JsonUtil.xml2Json(xml);
JSONArray jsonArray = resultJson.getJSONArray("inputproxychannel");
List<Integer> result = new ArrayList<>();
for (int i = 0; i < jsonArray.size(); i++) {
JSONObject j = jsonArray.getJSONObject(i);
result.add(j.getInteger("id"));
}
return result;
}
public void playBack(int lUserID, String ip, String port, @NotNull Date start, @NotNull Date end, String fileName, Integer taskId, Integer breastpieceId) {
HCISUPCMS.***_EHOME_PLAYBACK_INFO_IN pPlaybackInfoIn = new HCISUPCMS.***_EHOME_PLAYBACK_INFO_IN();
pPlaybackInfoIn.read();
pPlaybackInfoIn.dwSize = pPlaybackInfoIn.size();
pPlaybackInfoIn.dwChannel = 1;
pPlaybackInfoIn.byPlayBackMode = 1;
pPlaybackInfoIn.unionPlayBackMode.setType(HCISUPCMS.***_EHOME_PLAYBACKBYTIME.class);
Calendar cal = Calendar.getInstance();
cal.setTime(start);
pPlaybackInfoIn.unionPlayBackMode.struPlayBackbyTime.struStartTime.wYear = (short) cal.get(Calendar.YEAR);
pPlaybackInfoIn.unionPlayBackMode.struPlayBackbyTime.struStartTime.byMonth = (byte) (cal.get(Calendar.MONTH) + 1);
pPlaybackInfoIn.unionPlayBackMode.struPlayBackbyTime.struStartTime.byDay = (byte) cal.get(Calendar.DAY_OF_MONTH);
pPlaybackInfoIn.unionPlayBackMode.struPlayBackbyTime.struStartTime.byHour = (byte) cal.get(Calendar.HOUR_OF_DAY);
pPlaybackInfoIn.unionPlayBackMode.struPlayBackbyTime.struStartTime.byMinute = (byte) cal.get(Calendar.MINUTE);
pPlaybackInfoIn.unionPlayBackMode.struPlayBackbyTime.struStartTime.bySecond = (byte) cal.get(Calendar.SECOND);
cal.setTime(end);
pPlaybackInfoIn.unionPlayBackMode.struPlayBackbyTime.struStopTime.wYear = (short) cal.get(Calendar.YEAR);
pPlaybackInfoIn.unionPlayBackMode.struPlayBackbyTime.struStopTime.byMonth = (byte) (cal.get(Calendar.MONTH) + 1);
pPlaybackInfoIn.unionPlayBackMode.struPlayBackbyTime.struStopTime.byDay = (byte) cal.get(Calendar.DAY_OF_MONTH);
pPlaybackInfoIn.unionPlayBackMode.struPlayBackbyTime.struStopTime.byHour = (byte) cal.get(Calendar.HOUR_OF_DAY);
pPlaybackInfoIn.unionPlayBackMode.struPlayBackbyTime.struStopTime.byMinute = (byte) cal.get(Calendar.MINUTE);
pPlaybackInfoIn.unionPlayBackMode.struPlayBackbyTime.struStopTime.bySecond = (byte) cal.get(Calendar.SECOND);
System.arraycopy(ip.getBytes(), 0, pPlaybackInfoIn.struStreamSever.szIP, 0, ip.length());
pPlaybackInfoIn.struStreamSever.wPort = Short.parseShort(port);
pPlaybackInfoIn.write();
HCISUPCMS.***_EHOME_PLAYBACK_INFO_OUT pPlaybackInfoOut = new HCISUPCMS.***_EHOME_PLAYBACK_INFO_OUT();
pPlaybackInfoOut.write();
log.info("***_ECMS_StartPlayBack接口参数:{}", pPlaybackInfoIn);
if (hCEhomeCMS.***_ECMS_StartPlayBack(lUserID, pPlaybackInfoIn, pPlaybackInfoOut)) {
pPlaybackInfoOut.read();
log.info("***_ECMS_StartPlayBack su***ess");
} else {
log.info("***_ECMS_StartPlayBack failed, error code: {}", hCEhomeCMS.***_ECMS_GetLastError());
return;
}
HCISUPCMS.***_EHOME_PUSHPLAYBACK_IN m_struPushPlayBackIn = new HCISUPCMS.***_EHOME_PUSHPLAYBACK_IN();
m_struPushPlayBackIn.read();
m_struPushPlayBackIn.dwSize = m_struPushPlayBackIn.size();
m_struPushPlayBackIn.lSessionID = pPlaybackInfoOut.lSessionID;
m_struPushPlayBackIn.write();
HCISUPCMS.***_EHOME_PUSHPLAYBACK_OUT m_struPushPlayBackOut = new HCISUPCMS.***_EHOME_PUSHPLAYBACK_OUT();
m_struPushPlayBackOut.read();
m_struPushPlayBackOut.dwSize = m_struPushPlayBackOut.size();
m_struPushPlayBackOut.write();
log.info("***_ECMS_StartPushPlayBack接口参数:{}", m_struPushPlayBackIn);
if (hCEhomeCMS.***_ECMS_StartPushPlayBack(lUserID, m_struPushPlayBackIn, m_struPushPlayBackOut)) {
log.info("***_ECMS_StartPushPlayBack su***ess");
redisUtil.set("downloadHandle:" + m_struPushPlayBackOut.lHandle, fileName);
BreastpieceVideo breastpieceVideo = new BreastpieceVideo();
String[] names = fileName.split(OsSelect.isLinux()? "/" : "\\\\");
breastpieceVideo.setTaskId(taskId);
breastpieceVideo.setBreastpieceId(breastpieceId);
breastpieceVideo.setName(names[names.length - 1] + ".mp4");
breastpieceVideo.setAddress("http://47.101.185.231/ambulance-pc/video/breast/");
breastpieceVideo.setStartTime(start);
breastpieceVideo.setEndTime(end);
breastpieceVideoMapper.insert(breastpieceVideo);
} else {
log.info("***_ECMS_StartPushPlayBack failed, error code: {}", hCEhomeCMS.***_ECMS_GetLastError());
}
}
//注册回调函数
public class FRegisterCallBack implements HCISUPCMS.DEVICE_REGISTER_CB {
public String ip, port, breastpieceVideoPath;
@Override
public boolean invoke(int lUserID, int dwDataType, Pointer pOutBuffer, int dwOutLen, Pointer pInBuffer, int dwInLen, Pointer pUser) {
log.info("FRegisterCallBack, dwDataType:" + dwDataType + ", lUserID:" + lUserID);
HCISUPCMS.***_EHOME_DEV_REG_INFO_V12 strDevRegInfo;
Pointer pDevRegInfo;
if (dwDataType == 0 || dwDataType == 7) {
strDevRegInfo = new HCISUPCMS.***_EHOME_DEV_REG_INFO_V12();
strDevRegInfo.write();
pDevRegInfo = strDevRegInfo.getPointer();
pDevRegInfo.write(0, pOutBuffer.getByteArray(0, strDevRegInfo.size()), 0, strDevRegInfo.size());
strDevRegInfo.read();
HCISUPCMS.***_EHOME_SERVER_INFO_V50 strEhomeServerInfo = new HCISUPCMS.***_EHOME_SERVER_INFO_V50();
strEhomeServerInfo.read();
byte[] byCmsIP = new byte[0];
log.info(new String(byCmsIP));
String nvrCode = new String(strDevRegInfo.struRegInfo.byDeviceID).trim();
String nvrIp = new String(strDevRegInfo.struRegInfo.struDevAdd.szIP).trim();
log.info("Device online, DeviceID is:" + nvrCode);
log.info("Device online, DeviceIP is:" + nvrIp);
// 设备注册上线标志
userLoginMap.put(nvrCode,lUserID);
redisUtil.set("ip:" + nvrCode, nvrIp);
redisUtil.set("lUserID:" + nvrCode, lUserID);
redisUtil.set("carNo:" + lUserID, nvrCode);
if (nvrCode.startsWith("xp")) {
UpdateWrapper<Breastpiece> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("name", nvrCode);
Breastpiece breastpiece = new Breastpiece();
breastpiece.setIsOnline(1);
breastpieceMapper.update(breastpiece, updateWrapper);
QueryWrapper<Breastpiece> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name", nvrCode);
Breastpiece breastpieceL = breastpieceMapper.selectOne(queryWrapper);
//异步配置心跳监听。100秒没有收到心跳,设备离线
ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.submit(() -> {
try {
Thread.sleep(2000);
boolean heart = hCEhomeCMS.***_ECMS_SetAliveTimeout(lUserID, 100L, 1L);
if (heart) {
log.info("device {} ***_ECMS_SetAliveTimeout su***ess", nvrCode);
} else {
log.info("device {} ***_ECMS_SetAliveTimeout failed, error code: {}", nvrCode, hCEhomeCMS.***_ECMS_GetLastError());
}
Stream stream = CacheMap.get("stream");
stream.startListenPlayBack(ip, port);
List<TaskDetail> taskList = taskDetailMapper.selectListByDeviceCode(nvrCode);
if (taskList != null && taskList.size() > 0) {
taskList.forEach(t -> {
QueryWrapper<BreastpieceVideo> wrapper = new QueryWrapper<>();
wrapper.eq("task_id", t.getId());
Integer c = breastpieceVideoMapper.selectCount(wrapper);
if (c <= 0) {
playBack(lUserID, "47.101.185.231", port, t.getReceiveTime(), t.getDeliveryTime(), breastpieceVideoPath + t.getId(), t.getId(), breastpieceL.getId());
}
});
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});
executorService.shutdown();
}
return true;
} else if (dwDataType == 3) {
strDevRegInfo = new HCISUPCMS.***_EHOME_DEV_REG_INFO_V12();
strDevRegInfo.write();
pDevRegInfo = strDevRegInfo.getPointer();
pDevRegInfo.write(0, pOutBuffer.getByteArray(0, strDevRegInfo.size()), 0, strDevRegInfo.size());
strDevRegInfo.read();
String szEHomeKey = "12345678";
byte[] bs = szEHomeKey.getBytes();
pInBuffer.write(0, bs, 0, szEHomeKey.length());
} else if (dwDataType == 4) {
strDevRegInfo = new HCISUPCMS.***_EHOME_DEV_REG_INFO_V12();
strDevRegInfo.write();
pDevRegInfo = strDevRegInfo.getPointer();
pDevRegInfo.write(0, pOutBuffer.getByteArray(0, strDevRegInfo.size()), 0, strDevRegInfo.size());
strDevRegInfo.read();
log.info("byDeviceID:" + new String(strDevRegInfo.struRegInfo.byDeviceID).trim());
log.info("bySessionKey:" + new String(strDevRegInfo.struRegInfo.bySessionKey).trim());
HCISUPCMS.***_EHOME_DEV_SESSIONKEY struSessionKey = new HCISUPCMS.***_EHOME_DEV_SESSIONKEY();
System.arraycopy(strDevRegInfo.struRegInfo.byDeviceID, 0, struSessionKey.sDeviceID, 0, strDevRegInfo.struRegInfo.byDeviceID.length);
System.arraycopy(strDevRegInfo.struRegInfo.bySessionKey, 0, struSessionKey.sSessionKey, 0, strDevRegInfo.struRegInfo.bySessionKey.length);
struSessionKey.write();
Pointer pSessionKey = struSessionKey.getPointer();
hCEhomeCMS.***_ECMS_SetDeviceSessionKey(pSessionKey);
// mHCEHomeAlarm.***_EALARM_SetDeviceSessionKey(pSessionKey);
} else if (dwDataType == 5) {
String dasInfo = "{\n" +
" \"Type\":\"DAS\",\n" +
" \"DasInfo\":{\n" +
" \"Address\":\"47.101.185.231\",\n" +
" \"Domain\":\"\",\n" +
" \"ServerID\":\"\",\n" +
" \"Port\":20000,\n" +
" \"UdpPort\":\n" +
" }\n" +
"}";
byte[] bs1 = dasInfo.getBytes();
pInBuffer.write(0, bs1, 0, dasInfo.length());
} else if (dwDataType == 1) {
//设备离线
String deviceName = redisUtil.get("carNo:" + lUserID);
log.info("设备{}离线", deviceName);
if (deviceName.startsWith("xp")) {
//胸牌
UpdateWrapper<Breastpiece> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("name", deviceName);
Breastpiece breastpiece = new Breastpiece();
breastpiece.setIsOnline(0);
breastpieceMapper.update(breastpiece, updateWrapper);
}
redisUtil.delete("carNo:" + lUserID);
redisUtil.delete("ip:" + deviceName);
redisUtil.delete("lUserID:" + deviceName);
userLoginMap.remove(deviceName);
} else if (dwDataType == 8) {
//心跳
log.info("__心跳___");
log.info("FRegisterCallBack default type:" + dwDataType);
} else {
log.info("FRegisterCallBack default type:" + dwDataType);
}
return true;
}
}
public List<VideoFileInfoVo> findFile(int lLoginID, VideoFilesReq req) throws InterruptedException {
List<VideoFileInfoVo> result = new ArrayList<>();
HCISUPCMS.***_EHOME_REC_FILE_COND strufindCond = new HCISUPCMS.***_EHOME_REC_FILE_COND();
strufindCond.dwChannel = 1;
strufindCond.dwRecType = 0xff;
strufindCond.dwStartIndex = 0;
strufindCond.dwMaxFileCountPer = 10;
Calendar c = Calendar.getInstance();
c.setTime(req.getStart());
strufindCond.struStartTime.wYear = (short) c.get(Calendar.YEAR);
strufindCond.struStartTime.byMonth = (byte) (c.get(Calendar.MONTH) + 1);
strufindCond.struStartTime.byDay = (byte) c.get(Calendar.DAY_OF_MONTH);
strufindCond.struStartTime.byHour = (byte) c.get(Calendar.HOUR_OF_DAY);
strufindCond.struStartTime.byMinute = (byte) c.get(Calendar.MINUTE);
strufindCond.struStartTime.bySecond = (byte) c.get(Calendar.SECOND);
c.setTime(req.getEnd());
strufindCond.struStopTime.wYear = (short) c.get(Calendar.YEAR);
strufindCond.struStopTime.byMonth = (byte) (c.get(Calendar.MONTH) + 1);
strufindCond.struStopTime.byDay = (byte) c.get(Calendar.DAY_OF_MONTH);
strufindCond.struStopTime.byHour = (byte) c.get(Calendar.HOUR_OF_DAY);
strufindCond.struStopTime.byMinute = (byte) c.get(Calendar.MINUTE);
strufindCond.struStopTime.bySecond = (byte) c.get(Calendar.SECOND);
int lHandle = hCEhomeCMS.***_ECMS_StartFindFile_V11(lLoginID, 0, strufindCond, strufindCond.size());
if (lHandle < 0) {
log.info("***_ECMS_StartFindFile_V11 failed, error code: {}", hCEhomeCMS.***_ECMS_GetLastError());
} else {
log.info("***_ECMS_StartFindFile_V11 su***ess!");
while (true) {
HCISUPCMS.***_EHOME_REC_FILE struFileInfo = new HCISUPCMS.***_EHOME_REC_FILE();
int lRet = hCEhomeCMS.***_ECMS_FindNextFile_V11(lHandle, struFileInfo, struFileInfo.size());
if (lRet == 1000) {
//保存获取到的文件
VideoFileInfoVo vo = new VideoFileInfoVo();
vo.setFileName(new String(struFileInfo.sFileName));
log.info(vo.getFileName());
String fileSize;
if (struFileInfo.dwFileSize / 1024 == 0) {
fileSize = String.valueOf(struFileInfo.dwFileSize);
} else if (struFileInfo.dwFileSize / 1024 > 0 && struFileInfo.dwFileSize / (1024 * 1024) == 0) {
fileSize = struFileInfo.dwFileSize / 1024 + "K";
} else {
fileSize = struFileInfo.dwFileSize / (1024 * 1024) + "M";
}
vo.setSize(fileSize);
vo.setStart(String.format("%04d-%02d-%02d %02d:%02d:%02d", struFileInfo.struStartTime.wYear, struFileInfo.struStartTime.byMonth, struFileInfo.struStartTime.byDay, struFileInfo.struStartTime.byHour, struFileInfo.struStartTime.byMinute, struFileInfo.struStartTime.bySecond));
vo.setEnd(String.format("%04d-%02d-%02d %02d:%02d:%02d", struFileInfo.struStopTime.wYear, struFileInfo.struStopTime.byMonth, struFileInfo.struStopTime.byDay, struFileInfo.struStopTime.byHour, struFileInfo.struStopTime.byMinute, struFileInfo.struStopTime.bySecond));
result.add(vo);
} else if (lRet == 1002) {
Thread.sleep(5L);
} else {
break;
}
}
hCEhomeCMS.***_ECMS_StopFindFile(lHandle);
}
return result;
}
}
3.stream代码
package ***.ei.ambulance.util.isup;
import ***.ei.ambulance.util.RedisUtil;
import ***.ei.ambulance.util.hik.H***etSDK;
import ***.ei.ambulance.util.hik.OsSelect;
import ***.ei.ambulance.util.video.PushUtil;
import ***.sun.jna.Native;
import ***.sun.jna.Pointer;
import ***.sun.jna.ptr.IntByReference;
import lombok.extern.slf4j.Slf4j;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.nio.ByteBuffer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.***pletableFuture;
import java.util.concurrent.Executors;
@Slf4j
public class Stream {
public static Map<String,PipedOutputStream> streamMap = new HashMap<>();
public static RedisUtil redisUtil;
public static String rtmphost;
public static HCISUPStream hCEhomeStream = null;
public static PlayCtrl playCtrl = null;
static int m_lPlayBackLinkHandle = -1; //回放句柄
public static int m_lPlayBackListenHandle = -1; //回放监听句柄
public static int StreamHandle = -1; //预览监听句柄
public static Map<String,Integer> sessionMap = new HashMap<>(); //预览sessionID
public static Map<String,Integer> playHandleMap = new HashMap<>();
static int backSessionID = -1; //回放sessionID
static int Count = 0;
static int iCount = 0;
static IntByReference m_lPort = new IntByReference(-1);//回调预览时播放库端口指针
HCISUPStream.***_EHOME_PLAYBACK_LISTEN_PARAM struPlayBackListen = new HCISUPStream.***_EHOME_PLAYBACK_LISTEN_PARAM();
// HCISUPStream.***_EHOME_LISTEN_PREVIEW_CFG struPreviewListen = new HCISUPStream.***_EHOME_LISTEN_PREVIEW_CFG();
static FPREVIEW_NEWLINK_CB fPREVIEW_NEWLINK_CB;//预览监听回调函数实现
// static FPREVIEW_DATA_CB fPREVIEW_DATA_CB;//预览回调函数实现
public static Map<String,FPREVIEW_DATA_CB> dataMap = new HashMap<>();
static PLAYBACK_NEWLINK_CB fPLAYBACK_NEWLINK_CB; //回放监听回调函数实现
static PLAYBACK_DATA_CB fPLAYBACK_DATA_CB; //回放回调实现
/**
* 动态库加载
*
* @return
*/
private static boolean CreateSDKInstance() {
if (hCEhomeStream == null) {
synchronized (HCISUPStream.class) {
String strDllPath = "";
try {
if (OsSelect.isWindows())
//win系统加载库路径
strDllPath = System.getProperty("user.dir") + "\\lib\\isupsdk\\HCISUPStream.dll";
else if (OsSelect.isLinux())
//Linux系统加载库路径
strDllPath = System.getProperty("user.dir") + "/lib/isupsdkLinux/libHCISUPStream.so";
hCEhomeStream = (HCISUPStream) Native.loadLibrary(strDllPath, HCISUPStream.class);
} catch (Exception ex) {
log.info("loadLibrary: " + strDllPath + " Error: " + ex.getMessage());
return false;
}
}
}
return true;
}
public void eStream_Init() {
if (hCEhomeStream == null) {
if (!CreateSDKInstance()) {
log.info("Load Stream SDK fail");
return;
} else {
log.info("Load Stream SDK su***ess");
}
}
// if (playCtrl == null) {
// if (!CreatePlayInstance()) {
// log.info("Load PlayCtrl fail");
// return;
// } else {
// log.info("Load PlayCtrl SDK su***ess");
// }
//
// }
if (OsSelect.isWindows()) {
HCISUPCMS.BYTE_ARRAY ptrByteArrayCrypto = new HCISUPCMS.BYTE_ARRAY(256);
String strPathCrypto = System.getProperty("user.dir") + "\\lib\\isupsdk\\libeay32.dll"; //Linux版本是libcrypto.so库文件的路径
System.arraycopy(strPathCrypto.getBytes(), 0, ptrByteArrayCrypto.byValue, 0, strPathCrypto.length());
ptrByteArrayCrypto.write();
if (!hCEhomeStream.***_ESTREAM_SetSDKInitCfg(0, ptrByteArrayCrypto.getPointer())) {
log.info("***_ESTREAM_SetSDKInitCfg 0 failed, error:" + hCEhomeStream.***_ESTREAM_GetLastError());
}
HCISUPCMS.BYTE_ARRAY ptrByteArraySsl = new HCISUPCMS.BYTE_ARRAY(256);
String strPathSsl = System.getProperty("user.dir") + "\\lib\\isupsdk\\ssleay32.dll"; //Linux版本是libssl.so库文件的路径
System.arraycopy(strPathSsl.getBytes(), 0, ptrByteArraySsl.byValue, 0, strPathSsl.length());
ptrByteArraySsl.write();
if (!hCEhomeStream.***_ESTREAM_SetSDKInitCfg(1, ptrByteArraySsl.getPointer())) {
log.info("***_ESTREAM_SetSDKInitCfg 1 failed, error:" + hCEhomeStream.***_ESTREAM_GetLastError());
}
//流媒体初始化
hCEhomeStream.***_ESTREAM_Init();
//设置HCAapSDK***组件库文件夹所在路径
HCISUPCMS.BYTE_ARRAY ptrByteArray*** = new HCISUPCMS.BYTE_ARRAY(256);
String strPath*** = System.getProperty("user.dir") + "\\lib\\isupsdk\\HCAapSDK***"; //只支持绝对路径,建议使用英文路径
System.arraycopy(strPath***.getBytes(), 0, ptrByteArray***.byValue, 0, strPath***.length());
ptrByteArray***.write();
if (!hCEhomeStream.***_ESTREAM_SetSDKLocalCfg(5, ptrByteArray***.getPointer())) {
log.info("***_ESTREAM_SetSDKLocalCfg 5 failed, error:" + hCEhomeStream.***_ESTREAM_GetLastError());
}
hCEhomeStream.***_ESTREAM_SetLogToFile(3, System.getProperty("user.dir") + "/EHomeSDKLog", false);
} else if (OsSelect.isLinux()) {
//设置libcrypto.so所在路径
HCISUPCMS.BYTE_ARRAY ptrByteArrayCrypto = new HCISUPCMS.BYTE_ARRAY(256);
String strPathCrypto = System.getProperty("user.dir") + "/lib/libcrypto.so"; //Linux版本是libcrypto.so库文件的路径
System.arraycopy(strPathCrypto.getBytes(), 0, ptrByteArrayCrypto.byValue, 0, strPathCrypto.length());
ptrByteArrayCrypto.write();
if (!hCEhomeStream.***_ESTREAM_SetSDKInitCfg(0, ptrByteArrayCrypto.getPointer())) {
log.info("***_ESTREAM_SetSDKInitCfg 0 failed, error:" + hCEhomeStream.***_ESTREAM_GetLastError());
}
//设置libssl.so所在路径
HCISUPCMS.BYTE_ARRAY ptrByteArraySsl = new HCISUPCMS.BYTE_ARRAY(256);
String strPathSsl = System.getProperty("user.dir") + "/lib/libssl.so"; //Linux版本是libssl.so库文件的路径
System.arraycopy(strPathSsl.getBytes(), 0, ptrByteArraySsl.byValue, 0, strPathSsl.length());
ptrByteArraySsl.write();
if (!hCEhomeStream.***_ESTREAM_SetSDKInitCfg(1, ptrByteArraySsl.getPointer())) {
log.info("***_ESTREAM_SetSDKInitCfg 1 failed, error:" + hCEhomeStream.***_ESTREAM_GetLastError());
}
hCEhomeStream.***_ESTREAM_Init();
//设置HCAapSDK***组件库文件夹所在路径
HCISUPCMS.BYTE_ARRAY ptrByteArray*** = new HCISUPCMS.BYTE_ARRAY(256);
String strPath*** = System.getProperty("user.dir") + "/lib/HCAapSDK***/"; //只支持绝对路径,建议使用英文路径
System.arraycopy(strPath***.getBytes(), 0, ptrByteArray***.byValue, 0, strPath***.length());
ptrByteArray***.write();
if (!hCEhomeStream.***_ESTREAM_SetSDKLocalCfg(5, ptrByteArray***.getPointer())) {
log.info("***_ESTREAM_SetSDKLocalCfg 5 failed, error:" + hCEhomeStream.***_ESTREAM_GetLastError());
}
hCEhomeStream.***_ESTREAM_SetLogToFile(3, System.getProperty("user.dir") + "/EHomeSDKLog", false);
}
}
public void startRealPlayListen(String smsServerListenIP, String smsServerListenPort) {
//预览监听
if (fPREVIEW_NEWLINK_CB == null) {
fPREVIEW_NEWLINK_CB = new FPREVIEW_NEWLINK_CB();
}
HCISUPStream.***_EHOME_LISTEN_PREVIEW_CFG struPreviewListen = new HCISUPStream.***_EHOME_LISTEN_PREVIEW_CFG();
System.arraycopy(smsServerListenIP.getBytes(), 0, struPreviewListen.struIPAdress.szIP, 0, smsServerListenIP.length());
struPreviewListen.struIPAdress.wPort = Short.parseShort(smsServerListenPort); //流媒体服务器监听端口
struPreviewListen.fnNewLinkCB = fPREVIEW_NEWLINK_CB; //预览连接请求回调函数
struPreviewListen.pUser = null;
struPreviewListen.byLinkMode = 0; //0- TCP方式,1- UDP方式
struPreviewListen.write();
if (StreamHandle < 0) {
StreamHandle = hCEhomeStream.***_ESTREAM_StartListenPreview(struPreviewListen);
if (StreamHandle == -1) {
System.out.println("***_ESTREAM_StartListenPreview failed, error code:" + hCEhomeStream.***_ESTREAM_GetLastError());
hCEhomeStream.***_ESTREAM_Fini();
return;
} else {
String StreamListenInfo = new String(struPreviewListen.struIPAdress.szIP).trim() + "_" + struPreviewListen.struIPAdress.wPort;
System.out.println("流媒体服务:" + StreamListenInfo + ",***_ESTREAM_StartListenPreview su***eed");
}
}
}
/**
* 开启预览,
*
* @param carId
* @param lChannel 预览通道号
*/
public void realPlay(int lLoginId, String carId, int lChannel, String smsServerIP, String smsServerPort) throws Exception {
// JPanelDemo.jRealWinInit();
HCISUPCMS.***_EHOME_PREVIEWINFO_IN_V11 struPreviewIn = new HCISUPCMS.***_EHOME_PREVIEWINFO_IN_V11();
struPreviewIn.iChannel = lChannel; //通道号
struPreviewIn.dwLinkMode = 0; //0- TCP方式,1- UDP方式
struPreviewIn.dwStreamType = 0; //码流类型:0- 主码流,1- 子码流, 2- 第三码流
struPreviewIn.struStreamSever.szIP = smsServerIP.getBytes();//流媒体服务器IP地址,公网地址
struPreviewIn.struStreamSever.wPort = Short.parseShort(smsServerPort); //流媒体服务器端口,需要跟服务器启动监听端口一致
struPreviewIn.write();
//预览请求
HCISUPCMS.***_EHOME_PREVIEWINFO_OUT struPreviewOut = new HCISUPCMS.***_EHOME_PREVIEWINFO_OUT();
boolean getRS = Cms.hCEhomeCMS.***_ECMS_StartGetRealStreamV11(lLoginId, struPreviewIn, struPreviewOut);
// boolean getRS = Cms.hCEhomeCMS.***_ECMS_StartGetRealStream(Cms.lLoginID, struPreviewIn, struPreviewOut);
//Thread.sleep(10000);
if (!getRS) {
log.error("***_ECMS_StartGetRealStream failed, error code:{}", Cms.hCEhomeCMS.***_ECMS_GetLastError());
throw new Exception("摄像头不存在");
} else {
struPreviewOut.read();
log.info("***_ECMS_StartGetRealStream su***eed, sessionID:{}", struPreviewOut.lSessionID);
sessionMap.put("session:"+carId+"_"+lChannel,struPreviewOut.lSessionID);
}
HCISUPCMS.***_EHOME_PUSHSTREAM_IN struPushInfoIn = new HCISUPCMS.***_EHOME_PUSHSTREAM_IN();
struPushInfoIn.read();
struPushInfoIn.dwSize = struPushInfoIn.size();
struPushInfoIn.lSessionID = sessionMap.get("session:"+carId+"_"+lChannel);
struPushInfoIn.write();
HCISUPCMS.***_EHOME_PUSHSTREAM_OUT struPushInfoOut = new HCISUPCMS.***_EHOME_PUSHSTREAM_OUT();
struPushInfoOut.read();
struPushInfoOut.dwSize = struPushInfoOut.size();
struPushInfoOut.write();
if (!Cms.hCEhomeCMS.***_ECMS_StartPushRealStream(lLoginId, struPushInfoIn, struPushInfoOut)) {
sessionMap.remove("session:"+carId+"_"+lChannel);
log.error("***_ECMS_StartPushRealStream failed, error code:" + Cms.hCEhomeCMS.***_ECMS_GetLastError());
} else {
log.info("***_ECMS_StartPushRealStream su***eed, sessionID:" + struPushInfoIn.lSessionID);
}
}
/**
* 停止预览,Stream服务停止实时流转发,CMS向设备发送停止预览请求
*/
public void StopRealPlay(String carNo, Integer channel) {
Integer lPreviewHandle = playHandleMap.get("realPlayHandle:" + carNo+channel);
if (lPreviewHandle == null) {
return;
}
if (!hCEhomeStream.***_ESTREAM_StopPreview(lPreviewHandle)) {
System.out.println("***_ESTREAM_StopPreview failed,err = " + hCEhomeStream.***_ESTREAM_GetLastError());
return;
}
Integer loginId = Cms.userLoginMap.get(carNo);
if (loginId == null) {
return;
}
Integer sessionId = sessionMap.get("session:"+carNo+"_"+channel);
if (sessionId == null) {
return;
}
if (!Cms.hCEhomeCMS.***_ECMS_StopGetRealStream(loginId, sessionId)) {
log.info("***_ECMS_StopGetRealStream failed,err = " + Cms.hCEhomeCMS.***_ECMS_GetLastError());
return;
}
log.info("停止Stream的实时流转发");
Stream.dataMap.remove(carNo + "_" + channel);
Stream.sessionMap.remove("session:"+carNo+"_"+channel);
PipedOutputStream pos = streamMap.get("stream:" + lPreviewHandle);
if (pos != null) {
try {
pos.close();
} catch (IOException exception) {
exception.printStackTrace();
}
Stream.streamMap.remove("stream:"+ lPreviewHandle);
Stream.playHandleMap.remove("realPlayHandle:" + carNo+channel);
}
log.info("CMS发送预览停止请求");
}
/**
* 播放库加载
*
* @return
*/
private static boolean CreatePlayInstance() {
if (playCtrl == null) {
synchronized (PlayCtrl.class) {
String strPlayPath = "";
try {
if (OsSelect.isWindows())
//win系统加载库路径(路径不要带中文)
strPlayPath = System.getProperty("user.dir") + "\\lib\\isupsdk\\PlayCtrl.dll";
else if (OsSelect.isLinux())
//Linux系统加载库路径(路径不要带中文)
strPlayPath = System.getProperty("user.dir") + "/lib/libPlayCtrl.so";
playCtrl = (PlayCtrl) Native.loadLibrary(strPlayPath, PlayCtrl.class);
} catch (Exception ex) {
log.info("loadLibrary: " + strPlayPath + " Error: " + ex.getMessage());
return false;
}
}
}
return true;
}
public void startListenPlayBack(String ip, String port) {
if (fPLAYBACK_NEWLINK_CB == null) {
fPLAYBACK_NEWLINK_CB = new PLAYBACK_NEWLINK_CB();
}
HCISUPStream.***_EHOME_PLAYBACK_LISTEN_PARAM param = new HCISUPStream.***_EHOME_PLAYBACK_LISTEN_PARAM();
System.arraycopy(ip.getBytes(), 0, param.struIPAdress.szIP, 0, ip.length());
param.struIPAdress.wPort = Short.parseShort(port);
param.fnNewLinkCB = fPLAYBACK_NEWLINK_CB;
param.byLinkMode = 0;//tcp-0;udp-1
m_lPlayBackListenHandle = hCEhomeStream.***_ESTREAM_StartListenPlayBack(param);
if (m_lPlayBackListenHandle < -1) {
log.info("***_ESTREAM_StartListenPlayBack failed, error code: {}", hCEhomeStream.***_ESTREAM_GetLastError());
} else {
log.info("回放服务:{}_{}, ***_ESTREAM_StartListenPlayBack su***ess", ip, port);
}
}
public class FPREVIEW_NEWLINK_CB implements HCISUPStream.PREVIEW_NEWLINK_CB {
@Override
public boolean invoke(int lLinkHandle, HCISUPStream.***_EHOME_NEWLINK_CB_MSG pNewLinkCBMsg, Pointer pUserData) throws IOException {
// 监听,每realPlay调用时,此方法监听到,开始执行
String userId = new String(pNewLinkCBMsg.szDeviceID).trim();
int dwChannelNo = pNewLinkCBMsg.dwChannelNo;
PipedInputStream pis = new PipedInputStream();
PipedOutputStream pos = new PipedOutputStream();
Stream.streamMap.put("stream:"+lLinkHandle,pos);
pos.connect(pis);
***pletableFuture.runAsync(()-> {
try {
PushUtil.grabAndPushRtmp(pis,"rtmp://"+rtmphost+"/live/"+userId+"_"+ dwChannelNo);
} catch (Exception e) {
e.printStackTrace();
}
}, Executors.newFixedThreadPool(1));
log.info("FPREVIEW_NEWLINK_CB callback");
log.info("FPREVIEW_NEWLINK_CB callback byStreamType : {}", pNewLinkCBMsg.byStreamType);
//预览数据回调参数
playHandleMap.put("realPlayHandle:" + userId + dwChannelNo , lLinkHandle );
HCISUPStream.***_EHOME_PREVIEW_DATA_CB_PARAM struDataCB = new HCISUPStream.***_EHOME_PREVIEW_DATA_CB_PARAM();
FPREVIEW_DATA_CB fPREVIEW_DATA_CB = dataMap.get(userId + "_" + dwChannelNo);
if (fPREVIEW_DATA_CB == null) {
fPREVIEW_DATA_CB = new FPREVIEW_DATA_CB(pos);
dataMap.put(userId + "_" + dwChannelNo,fPREVIEW_DATA_CB);
}
struDataCB.fnPreviewDataCB = fPREVIEW_DATA_CB;
if (!hCEhomeStream.***_ESTREAM_SetPreviewDataCB(lLinkHandle, struDataCB)) {
log.info("***_ESTREAM_SetPreviewDataCB failed err::" + hCEhomeStream.***_ESTREAM_GetLastError());
return false;
}
return true;
}
}
public class FPREVIEW_DATA_CB implements HCISUPStream.PREVIEW_DATA_CB {
private PipedOutputStream pos;
public FPREVIEW_DATA_CB(PipedOutputStream pos) {
this.pos = pos;
}
//实时流回调函数/
@Override
public void invoke(int iPreviewHandle, HCISUPStream.***_EHOME_PREVIEW_CB_MSG pPreviewCBMsg, Pointer pUserData) throws Exception {
// if (Count == 500) {//降低打印频率
// log.info("FPREVIEW_DATA_CB callback, iPreviewHandle:{}", iPreviewHandle);
// log.info("FPREVIEW_DATA_CB callback, data length:" + pPreviewCBMsg.dwDataLen);
// Count = 0;
// }
// Count++;
long offset = 0;
ByteBuffer buffers = pPreviewCBMsg.pRecvdata.getByteBuffer(offset, pPreviewCBMsg.dwDataLen);
byte[] bytes = new byte[pPreviewCBMsg.dwDataLen];
buffers.rewind();
buffers.get(bytes);
try{
//2.将数据读入到内存空间,此处不可用redis,否则执行时间是当前10倍
// PipedOutputStream pos = Stream.streamMap.get("stream:"+iPreviewHandle);
pos.write(bytes);
} catch (Exception e) {
e.printStackTrace();
}
}
}
byte[] allEsBytes = null;
public void writeESH264(final byte[] outputData) throws IOException {
if (outputData.length <= 0) {
return;
}
if ((outputData[0] & 0xff) == 0x00
&& (outputData[1] & 0xff) == 0x00
&& (outputData[2] & 0xff) == 0x01
&& (outputData[3] & 0xff) == 0xBA) {
if (allEsBytes != null && allEsBytes.length > 0) {
return;
// allEsBytes = null;
}
}
if ((outputData[0] & 0xff) == 0x00
&& (outputData[1] & 0xff) == 0x00
&& (outputData[2] & 0xff) == 0x01
&& (outputData[3] & 0xff) == 0xE0) {
int from = 9 + outputData[8] & 0xff;
int len = outputData.length - 9 - (outputData[8] & 0xff);
byte[] esBytes = new byte[len];
System.arraycopy(outputData, from, esBytes, 0, len);
if (allEsBytes == null) {
allEsBytes = esBytes;
} else {
byte[] newEsBytes = new byte[allEsBytes.length + esBytes.length];
System.arraycopy(allEsBytes, 0, newEsBytes, 0, allEsBytes.length);
System.arraycopy(esBytes, 0, newEsBytes, allEsBytes.length, esBytes.length);
allEsBytes = newEsBytes;
}
} else {
allEsBytes = outputData;
}
}
void ffmpegConvetor(String videoInputPath, String videoOutPath) throws Exception {
if (OsSelect.isWindows()) {
String ffmpegExe = "E:\\chromeDowload\\ffmpeg.exe";
List<String> ***mand = new ArrayList<>();
***mand.add(ffmpegExe);
***mand.add("-i");
***mand.add(videoInputPath);
***mand.add("-c");
***mand.add("copy");
***mand.add("-an");
***mand.add(videoOutPath);
ProcessBuilder builder = new ProcessBuilder(***mand);
Process process = null;
try {
process = builder.start();
} catch (IOException e) {
e.printStackTrace();
}
// 使用这种方式会在瞬间大量消耗CPU和内存等系统资源,所以这里我们需要对流进行处理
try {
InputStream errorStream = process.getErrorStream();
InputStreamReader inputStreamReader = new InputStreamReader(errorStream);
BufferedReader br = new BufferedReader(inputStreamReader);
String line = "";
while ((line = br.readLine()) != null) {
}
if (br != null) {
br.close();
}
if (inputStreamReader != null) {
inputStreamReader.close();
}
if (errorStream != null) {
errorStream.close();
}
} catch (NullPointerException e) {
e.printStackTrace();
}
} else if (OsSelect.isLinux()) {
//todo linux的ffmpeg使用
}
}
public static class PLAYBACK_NEWLINK_CB implements HCISUPStream.PLAYBACK_NEWLINK_CB {
@Override
public boolean invoke(int lPlayBackLinkHandle, HCISUPStream.***_EHOME_PLAYBACK_NEWLINK_CB_INFO pNewLinkCBInfo, Pointer pUserData) {
pNewLinkCBInfo.read();
log.info("PLAYBACK_NEWLINK_CB callback, szDeviceID:" + new String(pNewLinkCBInfo.szDeviceID).trim()
+ ",lSessionID:" + pNewLinkCBInfo.lSessionID + ",dwChannelNo:" + pNewLinkCBInfo.dwChannelNo);
m_lPlayBackLinkHandle = lPlayBackLinkHandle;
HCISUPStream.***_EHOME_PLAYBACK_DATA_CB_PARAM struCBParam = new HCISUPStream.***_EHOME_PLAYBACK_DATA_CB_PARAM();
//预览数据回调参数
if (fPLAYBACK_DATA_CB == null) {
fPLAYBACK_DATA_CB = new PLAYBACK_DATA_CB();
}
// pNewLinkCBInfo.fnPlayBackDataCB = fPLAYBACK_DATA_CB;
// pNewLinkCBInfo.byStreamFormat = 0;
struCBParam.fnPlayBackDataCB = fPLAYBACK_DATA_CB;
struCBParam.byStreamFormat = 0;
struCBParam.write();
// pNewLinkCBInfo.write();
if (!hCEhomeStream.***_ESTREAM_SetPlayBackDataCB(lPlayBackLinkHandle, struCBParam)) {
log.info("***_ESTREAM_SetPlayBackDataCB failed");
}
return true;
}
}
public static class PLAYBACK_DATA_CB implements HCISUPStream.PLAYBACK_DATA_CB {
//实时流回调函数
@Override
public boolean invoke(int iPlayBackLinkHandle, HCISUPStream.***_EHOME_PLAYBACK_DATA_CB_INFO pDataCBInfo, Pointer pUserData) {
if (iCount == 500) {//降低打印频率
log.info("PLAYBACK_DATA_CB callback , dwDataLen:" + pDataCBInfo.dwDataLen + ",dwType:" + pDataCBInfo.dwType);
iCount = 0;
}
iCount++;
//播放库SDK解码显示在win窗口上,
switch (pDataCBInfo.dwType) {
case H***etSDK.***_DVR_SYSHEAD: //系统头
// boolean b_port = playCtrl.PlayM4_GetPort(m_lPort);
// if (b_port == false) //获取播放库未使用的通道号
// {
// break;
// }
// if (pDataCBInfo.dwDataLen > 0) {
// if (!playCtrl.PlayM4_SetOverlayMode(m_lPort.getValue(), false, 0)) {
// break;
// }
//
// if (!playCtrl.PlayM4_SetStreamOpenMode(m_lPort.getValue(), PlayCtrl.STREAME_FILE)) //设置文件流播放模式
// {
// break;
// }
//
// if (!playCtrl.PlayM4_OpenStream(m_lPort.getValue(), pDataCBInfo.pData, pDataCBInfo.dwDataLen, 2 * 1024 * 1024)) //打开流接口
// {
// break;
// }
// W32API.HWND hwnd = new W32API.HWND(Native.get***ponentPointer(IsupTest.panelRealplay));
// if (!playCtrl.PlayM4_Play(m_lPort.getValue(), hwnd)) //播放开始
// {
// break;
// }
// }
case H***etSDK.***_DVR_STREAMDATA: //码流数据
if (pDataCBInfo.dwDataLen > 0) {
// for (int i = 0; i < 1000; i++) {
// boolean bRet = playCtrl.PlayM4_InputData(m_lPort.getValue(), pDataCBInfo.pData, pDataCBInfo.dwDataLen);
// if (!bRet) {
// if (i >= 999) {
// log.info("PlayM4_InputData,failed err:" + playCtrl.PlayM4_GetLastError(m_lPort.getValue()));
// }
// try {
// Thread.sleep(1000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// } else {
// break;
// }
// }
try {
String fileName = redisUtil.get("downloadHandle:" + iPlayBackLinkHandle);
FileOutputStream m_file = new FileOutputStream(fileName, true);
long offset = 0;
ByteBuffer buffers = pDataCBInfo.pData.getByteBuffer(offset, pDataCBInfo.dwDataLen);
byte[] bytes = new byte[pDataCBInfo.dwDataLen];
buffers.rewind();
buffers.get(bytes);
m_file.write(bytes);
m_file.close();
// if (pDataCBInfo.dwDataLen < 1024)
// VideoUtil.convetor(fileName, fileName + ".mp4");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
break;
//如果仅需保存回放的视频流文件,参考一下注释的代码
/*try {
m_file = new FileOutputStream(file, true);
long offset = 0;
ByteBuffer buffers = pDataCBInfo.pData.getByteBuffer(offset, pDataCBInfo.dwDataLen);
byte [] bytes = new byte[pDataCBInfo.dwDataLen];
buffers.rewind();
buffers.get(bytes);
m_file.write(bytes);
m_file.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/
case 3: //结束
String fileName = redisUtil.get("downloadHandle:" + iPlayBackLinkHandle);
try {
if (OsSelect.isLinux()) {
convetorLinux(fileName, fileName + ".mp4");
} else {
convetorWindows(fileName, fileName + ".mp4");
}
break;
}catch (Exception ex) {
ex.printStackTrace();
}
}
return true;
}
}
public static void convetorWindows(String videoInputPath, String videoOutPath) throws Exception{
String ffmpegExe = "E:\\software\\ffmpeg-5.0.1-essentials_build\\bin\\ffmpeg.exe";
List<String> ***mand = new ArrayList<>();
***mand.add(ffmpegExe);
***mand.add("-i");
***mand.add(videoInputPath);
***mand.add("-c");
***mand.add("copy");
***mand.add("-an");
***mand.add(videoOutPath);
ProcessBuilder builder = new ProcessBuilder(***mand);
Process process = null;
try {
process = builder.start();
} catch (IOException e) {
e.printStackTrace();
}
// 使用这种方式会在瞬间大量消耗CPU和内存等系统资源,所以这里我们需要对流进行处理
try {
InputStream errorStream = process.getErrorStream();
InputStreamReader inputStreamReader = new InputStreamReader(errorStream);
BufferedReader br = new BufferedReader(inputStreamReader);
String line = "";
while ((line = br.readLine()) != null) {
}
if (br != null) {
br.close();
}
if (inputStreamReader != null) {
inputStreamReader.close();
}
if (errorStream != null) {
errorStream.close();
}
Path p = Paths.get(videoInputPath);
Files.delete(p);
} catch (NullPointerException e) {
e.printStackTrace();
}
}
public static void convetorLinux(String videoInputPath, String videoOutPath) throws Exception {
String ffmpegExe = "/usr/local/ffmpeg/bin/ffmpeg";
String video***mend = ffmpegExe + " -i " + videoInputPath + " -c copy -an " + videoOutPath;
try {
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec(video***mend);
InputStream stderr = proc.getErrorStream();
InputStreamReader isr = new InputStreamReader(stderr);
BufferedReader br = new BufferedReader(isr);
String line = null;
while ((line = br.readLine()) != null){
}
if (br != null) {
br.close();
}
if (isr != null) {
isr.close();
}
if (stderr != null) {
stderr.close();
}
int exitVal = proc.waitFor();
Path p = Paths.get(videoInputPath);
Files.delete(p);
} catch (Throwable t) {
t.printStackTrace();
}
}
}