Commit 9dad6797 authored by 李成龙's avatar 李成龙

V1.2版本,增加数据权限

parents
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.yeejoin.amos</groupId>
<artifactId>HikVideo</artifactId>
<version>1.0.0</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope> </dependency> -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15</classifier>
</dependency>
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.1.41</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-all</artifactId>
<version>1.7.6</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/jackson-all-1.7.6.jar</systemPath>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>org.apache.axis2</groupId>
<artifactId>axis2</artifactId>
<version>1.6.2</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/axis2-1.6.2.jar</systemPath>
</dependency>
<dependency>
<groupId>com.hikvision</groupId>
<artifactId>ivms6-swdf-core</artifactId>
<version>1.1.2-SNAPSHOT</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/ivms6-swdf-core-1.1.2-20141027.031632-20.jar</systemPath>
</dependency>
<dependency>
<groupId>com.hikvision</groupId>
<artifactId>hik-cache</artifactId>
<version>1.1.5</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/hik-cache-1.1.5.jar</systemPath>
</dependency>
<dependency>
<groupId>com.hikvision</groupId>
<artifactId>hik-scheduler</artifactId>
<version>1.1.1</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/hik-scheduler-1.1.1-20140530.043726-1.jar</systemPath>
</dependency>
<dependency>
<groupId>com.hikvision</groupId>
<artifactId>hik-util</artifactId>
<version>1.0.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/hik-util-1.0.0.jar</systemPath>
</dependency>
<!-- <dependency> <groupId>com.hikvision</groupId> <artifactId>platform-message-util</artifactId>
<version>4.2-SNAPSHOT</version> <scope>system</scope> <systemPath>${project.basedir}/lib/platform-message-util-4.2-SNAPSHOT.jar</systemPath>
</dependency> -->
<dependency>
<groupId>org.apache.axis2</groupId>
<artifactId>axis2-transport-http</artifactId>
<version>1.6.2</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/axis2-transport-http-1.6.2.jar</systemPath>
</dependency>
<dependency>
<groupId>org.apache.axis2</groupId>
<artifactId>axis2-transport-local</artifactId>
<version>1.6.2</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/axis2-transport-local-1.6.2.jar</systemPath>
</dependency>
<dependency>
<groupId>org.apache.neethi</groupId>
<artifactId>neethi</artifactId>
<version>3.0.2</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/neethi-3.0.2.jar</systemPath>
</dependency>
<dependency>
<groupId>org.apache.ws.commons.axiom</groupId>
<artifactId>axiom-api</artifactId>
<version>1.2.13</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/axiom-api-1.2.13.jar</systemPath>
</dependency>
<dependency>
<groupId>org.apache.ws.commons.axiom</groupId>
<artifactId>axiom-impl</artifactId>
<version>1.2.13</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/axiom-impl-1.2.13.jar</systemPath>
</dependency>
<!-- <dependency> <groupId>com.ibm.wsdl</groupId> <artifactId>wsdl4j</artifactId>
<version>1.6.2</version> <scope>system</scope> <systemPath>${project.basedir}/lib/wsdl4j-1.6.2.jar</systemPath>
</dependency> -->
<!-- <dependency> <groupId>com.ctc.wstx</groupId> <artifactId>wstx-asl</artifactId>
<version>3.2.9</version> <scope>system</scope> <systemPath>${project.basedir}/lib/wstx-asl-3.2.9.jar</systemPath>
</dependency> -->
<dependency>
<groupId>org.apache.woden</groupId>
<artifactId>woden-api</artifactId>
<version>1.0M9</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/woden-api-1.0M9.jar</systemPath>
</dependency>
<dependency>
<groupId>org.apache.woden</groupId>
<artifactId>woden-impl-commons</artifactId>
<version>1.0M9</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/woden-impl-commons-1.0M9.jar</systemPath>
</dependency>
<dependency>
<groupId>org.apache.woden</groupId>
<artifactId>woden-impl-dom</artifactId>
<version>1.0M9</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/woden-impl-dom-1.0M9.jar</systemPath>
</dependency>
<dependency>
<groupId>org.apache.ws.commons.schema</groupId>
<artifactId>XmlSchema</artifactId>
<version>1.4.7</version>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.6</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>3.7.5</version>
</dependency>
<dependency>
<groupId>com.github.jsqlparser</groupId>
<artifactId>jsqlparser</artifactId>
<version>0.9.1</version>
</dependency>
<!-- 通用Mapper -->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper</artifactId>
<version>4.0.3</version>
</dependency><!-- apache httpclient组件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>lib</directory>
<targetPath>lib/</targetPath>
<includes>
<include>**/*.jar</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>1.3.5.RELEASE</version>
<configuration>
<!-- 指定启动类 -->
<mainClass>com.yeejoin.amos.AppStart</mainClass>
<includeSystemScope>true</includeSystemScope>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
package com.yeejoin.amos;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ImportResource;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
import com.yeejoin.amos.rtsp.HtmlRtspPlayerWebSockerServer;
import com.yeejoin.amos.rtsp.WebSocketHandshakeInterceptor;
@EnableScheduling
@EnableWebSocket
@SpringBootApplication
//@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
@ImportResource(locations = {"classpath:config/applicationXml/application-*.xml"})
@MapperScan(basePackages ={"com.yeejoin.amos.mapper"})
public class AppStart
implements WebSocketConfigurer
{
public static void main(String[] args) {
new SpringApplication(AppStart.class).run(args);
}
@Bean
public HtmlRtspPlayerWebSockerServer htmlRtspPlayerWebSockerServer() {
return new HtmlRtspPlayerWebSockerServer();
}
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(htmlRtspPlayerWebSockerServer(), "/player").setAllowedOrigins("*").addInterceptors(new WebSocketHandshakeInterceptor());
}
}
package com.yeejoin.amos;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import org.springframework.core.annotation.Order;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.stereotype.Component;
/**
* <pre>
* 跨域处理
* </pre>
*
* @author SmartRay
* @version CrossDomainFilter.java v0.1
* @time 2016-9-7 9:48:10
*/
@Component(value = "crossDomainFilter")
@EnableScheduling
@Order(0)
public class CrossDomainFilter implements Filter
{
public void destroy()
{
}
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException
{
HttpServletResponse response = (HttpServletResponse) res;
// 允许所有域进行访问
response.setHeader("Access-Control-Allow-Origin", "*");
// 允许的方法
response.setHeader("Access-Control-Allow-Methods","GET,POST,DELETE,OPTIONS,PUT");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers","Origin, X-Requested-With, X-Access-Token, X-Api-Key, Content-Type, Accept, Cache-Control,product,token,appKey");
chain.doFilter(req, res);
}
public void init(FilterConfig arg0) throws ServletException
{
}
}
package com.yeejoin.amos.controller;
import com.alibaba.fastjson.JSONObject;
import com.yeejoin.amos.entity.MonitorParam;
import com.yeejoin.amos.entity.PageModel;
import com.yeejoin.amos.entity.RtspAddressBean;
import com.yeejoin.amos.entity.Video;
import com.yeejoin.amos.response.CommonResponse;
import com.yeejoin.amos.server.ParamsConfig;
import com.yeejoin.amos.service.PageService;
import com.yeejoin.amos.service.VideoService;
import com.yeejoin.amos.util.CommonResponseUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
@RestController
@RequestMapping(value = "/rtsp")
public class AddressController {
private final Logger log = LoggerFactory.getLogger(AddressController.class);
@Autowired
VideoService videoService;
@Autowired
private PageService pageService;
@PostMapping(value = "/address", produces = "application/json;charset=UTF-8")
public CommonResponse getRtspAddress(@RequestBody List<RtspAddressBean> list) {
try {
// URL
List<String> listUrls = new ArrayList<>();
for (RtspAddressBean bean : list) {
// rtsp://admin:zjt123456@172.16.18.21:554/h264/ch1/main/av_stream
String url = "rtsp://" + bean.getUserName() + ":" + bean.getPwd() + "@" + bean.getIp() + ":"
+ bean.getPort() + "/" + bean.getVideoFormat() + "/" + bean.getChannel() + "/main/av_stream";
listUrls.add(url);
}
return CommonResponseUtil.success(listUrls);
} catch (Exception e) {
log.error(e.getMessage(), e);
return CommonResponseUtil.failure("获取地址失败");
}
}
/**
* 分页查询摄像头列表
* @param param
* @return
*/
@PostMapping(value = "/listVideoByPage", produces = "application/json;charset=UTF-8")
public CommonResponse getVideos(@RequestBody(required = true) MonitorParam param) {
try {
PageModel<Video> findRoadPageList = videoService.findPageList(param);
return CommonResponseUtil.success(findRoadPageList);
} catch (Exception e) {
log.error(e.getMessage(), e);
return CommonResponseUtil.failure("获取失败");
}
}
/**
* 获取所有节点列表(树结构)
* @return
*/
@GetMapping(value = "/list", produces = "application/json;charset=UTF-8")
public CommonResponse getVideosList(@RequestParam("floor3d") String floor3d) {
try {
List<Video> findAll = videoService.findAll(floor3d);
return CommonResponseUtil.success(findAll);
} catch (Exception e) {
log.error(e.getMessage(), e);
return CommonResponseUtil.failure("获取失败");
}
}
/**
* 获取所有节点列表(树结构)
* @return
*/
@GetMapping(value = "/monitorVideoTree", produces = "application/json;charset=UTF-8")
public CommonResponse getVideosTree() {
try {
List<Map<String, Object>> resultList = videoService.videoTree();
return CommonResponseUtil.success(resultList);
} catch (Exception e) {
log.error(e.getMessage(), e);
return CommonResponseUtil.failure("获取失败");
}
}
/**
* 分页查询摄像头列表
* @param param
* @return
*/
@PostMapping(value = "/monitorVideoByPage", produces = "application/json;charset=UTF-8")
public CommonResponse getPageMonitorVideo(@RequestBody(required = true) MonitorParam param){
List list = pageService.doService(param);
return CommonResponseUtil.success(list);
}
}
package com.yeejoin.amos.controller;
import javax.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.yeejoin.amos.entity.H5Response;
import com.yeejoin.amos.entity.Video;
import com.yeejoin.amos.response.CommonResponse;
import com.yeejoin.amos.server.ParamsConfig;
import com.yeejoin.amos.server.RemoteServer;
import com.yeejoin.amos.service.VideoService;
import com.yeejoin.amos.util.CommonResponseUtil;
@RestController
@RequestMapping(value = "/video")
public class VideoController {
private final Logger log = LoggerFactory.getLogger(VideoController.class);
@Autowired
VideoService videoService;
@Resource(name = "paramsConfig")
private ParamsConfig paramsConfig;
@Autowired
RemoteServer server;
/**
* 添加设备
* @param list
* @return
*/
@PostMapping(value = "/addDevice", produces = "application/json;charset=UTF-8")
public CommonResponse getAddDevice(@RequestBody Video bean) {
try {
H5Response addDevice = videoService.addDevice(bean);
if(addDevice.isbStatus()) {
log.info("add device success!");
return CommonResponseUtil.success(bean);
}else {
log.error("add device fail!");
return CommonResponseUtil.failure("add device fail!");
}
} catch (Exception e) {
log.error(e.getMessage(), e);
return CommonResponseUtil.failure("添加设备失败");
}
}
/**
* 获取设备信息
* @return
*/
@GetMapping(value = "/getDeviceMsg", produces = "application/json;charset=UTF-8")
public CommonResponse getDeviceMsg(@RequestParam(value ="token") String token) {
try {
Video device = videoService.getDevice(token);
if(null!=device) {
return CommonResponseUtil.success(device);
}else {
return CommonResponseUtil.failure("该设备不存在");
}
} catch (Exception e) {
log.error(e.getMessage(), e);
return CommonResponseUtil.failure("获取设备信息失败");
}
}
/**
* 删除设备信息
* @return
*/
@DeleteMapping(value = "/deleteDeviceMsg", produces = "application/json;charset=UTF-8")
public CommonResponse deleteDevice(@RequestParam(value ="token") String token) {
try {
H5Response deleteDevice = videoService.deleteDevice(token);
if(deleteDevice.isbStatus()) {
log.info("delete device success!");
return CommonResponseUtil.success(deleteDevice);
}else {
log.error("delete device fail!");
return CommonResponseUtil.failure("设备不存在");
}
} catch (Exception e) {
log.error(e.getMessage(), e);
return CommonResponseUtil.failure("获取设备信息失败");
}
}
/**
* 更新设备楼层和三维信息
* @param bean
* @return
*/
@PutMapping(value = "/updateDevice", produces = "application/json;charset=UTF-8")
public CommonResponse updateDevice(@RequestBody Video bean) {
try {
if(null==bean.getId()) {
return CommonResponseUtil.failure("设备token不可为空");
}
videoService.updateDevice(bean);
return CommonResponseUtil.success();
} catch (Exception e) {
log.error(e.getMessage(), e);
return CommonResponseUtil.failure("更新设备失败");
}
}
}
package com.yeejoin.amos.dao;
import com.yeejoin.amos.entity.Video;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface IVideoDao extends JpaRepository<Video, Long> {
}
package com.yeejoin.amos.entity;
import java.io.Serializable;
/**
* 摄像头配置参数
* @author DELL
*
*/
public class App implements Serializable{
/**
* serialVersionUID
*/
private static final long serialVersionUID = 1L;
//摄像头应用名称
private String appName;
//rtsp地址
private String input;
//应用地址
private String output;
public String getAppName() {
return appName;
}
public void setAppName(String appName) {
this.appName = appName;
}
public String getInput() {
return input;
}
public void setInput(String input) {
this.input = input;
}
public String getOutput() {
return output;
}
public void setOutput(String output) {
this.output = output;
}
@Override
public String toString() {
return "App [appName=" + appName + ", input=" + input + ", output=" + output + "]";
}
}
package com.yeejoin.amos.entity;
/**
* 用于请求和返回数据使用
*
*/
public class BaseParam {
Long id;
/**
* 页码,默认值1
*/
protected Integer current = 1;
/**
* 每页记录数
*/
private Integer pageSize;
/**
* 设备名称
*/
private String name;
/**
* 是否叶子节点,默认true
*/
private Boolean isLeaf = true;
/**
* 从第几条记录开始查
* @return
*/
public Integer getStartPage(){
if(current!=null && current==0) {
return 0;
}
return (current - 1) * pageSize;
}
public Integer getCurrent() {
return current;
}
public void setCurrent(Integer current) {
this.current = current;
}
public void setPageNum(Integer current) {
this.current = current;
}
public Integer getPageSize() {
if(current!=null && current==0) {
return Integer.MAX_VALUE;
}
return pageSize;
}
public void setPageSize(Integer pageSize) {
this.pageSize = pageSize;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Boolean getIsLeaf() {
return isLeaf;
}
public void setIsLeaf(Boolean isLeaf) {
this.isLeaf = isLeaf;
}
}
package com.yeejoin.amos.entity;
public class DeviceBean {
private String strName;
private String strUrl;
private String strSrcIpAddress;
private String strPasswd;
private String strUser;
private String strToken;
public String getStrName() {
return strName;
}
public void setStrName(String strName) {
this.strName = strName;
}
public String getStrUrl() {
return strUrl;
}
public void setStrUrl(String strUrl) {
this.strUrl = strUrl;
}
public String getStrSrcIpAddress() {
return strSrcIpAddress;
}
public void setStrSrcIpAddress(String strSrcIpAddress) {
this.strSrcIpAddress = strSrcIpAddress;
}
public String getStrPasswd() {
return strPasswd;
}
public void setStrPasswd(String strPasswd) {
this.strPasswd = strPasswd;
}
public String getStrUser() {
return strUser;
}
public void setStrUser(String strUser) {
this.strUser = strUser;
}
public String getStrToken() {
return strToken;
}
public void setStrToken(String strToken) {
this.strToken = strToken;
}
}
package com.yeejoin.amos.entity;
public class H5Response {
private boolean bStatus;
private String strCode;
public boolean isbStatus() {
return bStatus;
}
public void setbStatus(boolean bStatus) {
this.bStatus = bStatus;
}
public String getStrCode() {
return strCode;
}
public void setStrCode(String strCode) {
this.strCode = strCode;
}
}
package com.yeejoin.amos.entity;
/**
* @Author: xinglei
* @Description: TODO()
* @Date: 2019/11/27 17:31
*/
public class MonitorParam extends BaseParam {
/**
* 父ID
*/
private Long parentId;
public Long getParentId() {
return parentId;
}
public void setParentId(Long parentId) {
this.parentId = parentId;
}
}
package com.yeejoin.amos.entity;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.data.domain.Page;
/**
* 分页返回模板对象
*
* @param <T>
*/
public class PageModel<T> {
/**
* 总记录数
*/
private Integer total;
/**
* 当前页数
*/
private Integer currPage;
/**
* 总页数
*/
private Integer totalPage;
/**
* 每页记录数
*/
private Integer pageSize;
/**
* 数据
*/
private List<T> dataList;
public PageModel(){
super();
}
public PageModel(Integer total, Integer currPage, Integer pageSize, List<T> dataList) {
super();
this.total = total;
this.currPage = currPage;
this.pageSize = pageSize;
this.dataList = dataList;
totalPage = (total - 1)/pageSize + 1;
}
public PageModel(Integer currPage, Integer pageSize, List<T> dataAll) {
super();
this.total = dataAll.size();
this.currPage = currPage;
this.pageSize = pageSize;
List<T> subList = null;
Integer start = pageSize*(currPage-1);
if(start >= dataAll.size()) {
subList = new ArrayList<>();
}else if(start+pageSize >= dataAll.size()) {
subList = dataAll.subList(start,dataAll.size());
}else {
subList = dataAll.subList(start, start+pageSize);
}
this.dataList = subList;
totalPage = (total - 1)/pageSize + 1;
}
/**
* jpa查询得到的分页转换为PageModel
* @param page
*/
public PageModel(Page<T> page){
long t = page.getTotalElements();
this.total = ((Long)t).intValue();
this.currPage = page.getNumber()+1;
this.pageSize = page.getSize();
this.dataList = page.getContent();
this.totalPage = page.getTotalPages();
}
public Integer getPageSize() {
return pageSize;
}
public void setPageSize(Integer pageSize) {
this.pageSize = pageSize;
}
public Integer getTotal() {
return total;
}
public void setTotal(Integer total) {
this.total = total;
}
public Integer getCurrPage() {
return currPage;
}
public void setCurrPage(Integer currPage) {
this.currPage = currPage;
}
public Integer getTotalPage() {
return totalPage;
}
public void setTotalPage(Integer totalPage) {
this.totalPage = totalPage;
}
public List<T> getDataList() {
return dataList;
}
public void setDataList(List<T> dataList) {
this.dataList = dataList;
}
/**
* 本方法用于方便前端处理分页参数
* @return
*/
public Map<String, Object> getParameterMap(){
Map<String, Object> map = new HashMap<String, Object>();
map.put("current", currPage);
map.put("total", total);
map.put("pageSize", pageSize);
return map;
}
}
package com.yeejoin.amos.entity;
public class RtspAddressBean {
private String userName;
private String pwd;
private String ip;
private String port;
//编码格式
private String videoFormat;
//通道
private String channel;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public String getPort() {
return port;
}
public void setPort(String port) {
this.port = port;
}
public String getVideoFormat() {
return videoFormat;
}
public void setVideoFormat(String videoFormat) {
this.videoFormat = videoFormat;
}
public String getChannel() {
return channel;
}
public void setChannel(String channel) {
this.channel = channel;
}
@Override
public String toString() {
return "RtspAddressBean [userName=" + userName + ", pwd=" + pwd + ", ip=" + ip + ", port=" + port
+ ", videoFormat=" + videoFormat + ", channel=" + channel + "]";
}
}
package com.yeejoin.amos.entity;
import java.util.Map;
public class RtspSource {
private boolean bStatus;
Map<String, Object>[] src;
public Map<String, Object>[] getSrc() {
return src;
}
public void setSrc(Map<String, Object>[] src) {
this.src = src;
}
public boolean getbStatus() {
return bStatus;
}
public void setbStatus(boolean bStatus) {
this.bStatus = bStatus;
}
}
package com.yeejoin.amos.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import java.io.Serializable;
@Entity
@Table(name = "b_monitor_video")
@org.hibernate.annotations.Table(appliesTo = "b_monitor_video", comment = "摄像头信息表")
public class Video implements Serializable {
private static final long serialVersionUID = 3499756800920010671L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = true)
private Long id;
@Column(name = "name", columnDefinition = "varchar(255) COMMENT '设备名称'")
private String name;
@Column(name = "parent_id", columnDefinition = "varchar(255) COMMENT '父ID'")
private Long parentId;
@Column(name = "is_leaf", columnDefinition = "bit COMMENT '是否叶子节点'")
private Integer isLeaf;
@Column(name = "ip", columnDefinition = "varchar(255) COMMENT '设备IP'")
private String ip;
@Column(name = "rtsp_address", columnDefinition = "varchar(255) COMMENT '视频rtsp地址'")
private String rtspAddress;
@Column(name = "url", columnDefinition = "varchar(255) COMMENT '视频访问url'")
private String url;
@Column(name = "text", columnDefinition = "varchar(255) COMMENT '备注'")
private String text;
@Column(name = "carmera_type", columnDefinition = "varchar(255) COMMENT '设备类型'")
private String carmeraType;
@Column(name = "position3d", columnDefinition = "varchar(255) COMMENT '三维坐标信息'")
private String position3d;
@Column(name = "floor3d", columnDefinition = "varchar(255) COMMENT '楼层'")
private String floor3d;
@Column(name = "is_indoor", columnDefinition = "bit COMMENT '室内室外:1 为室内,0为室外'")
private Boolean isIndoor;
@Column(name = "status", columnDefinition = "int(10) COMMENT '监控视频状态:【1:正常;0:异常】'")
private int status;
@Column(name = "token", columnDefinition = "varchar(255) COMMENT '摄像头唯一token'")
private String token;
@Column(name = "user", columnDefinition = "varchar(255) COMMENT '用户名'")
private String user;
@Column(name = "password", columnDefinition = "varchar(255) COMMENT '密码'")
private String password;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getParentId() {
return parentId;
}
public void setParentId(Long parentId) {
this.parentId = parentId;
}
public Integer getIsLeaf() {
return isLeaf;
}
public void setIsLeaf(Integer isLeaf) {
this.isLeaf = isLeaf;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public String getRtspAddress() {
return rtspAddress;
}
public void setRtspAddress(String rtspAddress) {
this.rtspAddress = rtspAddress;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getCarmeraType() {
return carmeraType;
}
public void setCarmeraType(String carmeraType) {
this.carmeraType = carmeraType;
}
public String getPosition3d() {
return position3d;
}
public void setPosition3d(String position3d) {
this.position3d = position3d;
}
public String getFloor3d() {
return floor3d;
}
public void setFloor3d(String floor3d) {
this.floor3d = floor3d;
}
public Boolean getIsIndoor() {
return isIndoor;
}
public void setIsIndoor(Boolean isIndoor) {
this.isIndoor = isIndoor;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
package com.yeejoin.amos.ffmpeg;
import java.util.Collection;
import java.util.Map;
import static com.yeejoin.amos.ffmpeg.utils.PropertiesUtil.load;
import com.yeejoin.amos.ffmpeg.commandbuidler.CommandAssembly;
import com.yeejoin.amos.ffmpeg.commandbuidler.CommandBuidler;
import com.yeejoin.amos.ffmpeg.config.ProgramConfig;
import com.yeejoin.amos.ffmpeg.data.CommandTasker;
import com.yeejoin.amos.ffmpeg.data.TaskDao;
import com.yeejoin.amos.ffmpeg.hander.TaskHandler;
/**
* FFmpeg命令操作管理器,可执行FFmpeg命令/停止/查询任务信息
*
* @author eguid
* @since jdk1.7
* @version 2016年10月29日
*/
public interface CommandManager {
public static final ProgramConfig config=load("/loadFFmpeg.properties", ProgramConfig.class);
/**
* 注入自己实现的持久层
*
* @param taskDao
*/
public void setTaskDao(TaskDao taskDao);
/**
* 注入ffmpeg命令处理器
*
* @param taskHandler
*/
public void setTaskHandler(TaskHandler taskHandler);
/**
* 注入ffmpeg命令组装器
*
* @param commandAssembly
*/
public void setCommandAssembly(CommandAssembly commandAssembly);
/**
* 通过命令发布任务(默认命令前不加FFmpeg路径)
*
* @param id - 任务标识
* @param command - FFmpeg命令
* @return
*/
public String start(String id, String command);
/**
* 通过命令发布任务
* @param id - 任务标识
* @param commond - FFmpeg命令
* @param hasPath - 命令中是否包含FFmpeg执行文件的绝对路径
* @return
*/
public String start(String id,String commond,boolean hasPath);
/**
* 通过流式命令构建器发布任务
* @param commandBuidler
* @return
*/
public String start(String id,CommandBuidler commandBuidler);
/**
* 通过组装命令发布任务
*
* @param assembly
* -组装命令(详细请参照readme文档说明)
* @return
*/
public String start(Map<String,String> assembly);
/**
* 停止任务
*
* @param id
* @return
*/
public boolean stop(String id);
/**
* 停止全部任务
*
* @return
*/
public int stopAll();
/**
* 通过id查询任务信息
*
* @param id
*/
public CommandTasker query(String id);
/**
* 查询全部任务信息
*
*/
public Collection<CommandTasker> queryAll();
/**
* 销毁一些后台资源和保活线程
*/
public void destory();
}
package com.yeejoin.amos.ffmpeg;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import com.yeejoin.amos.ffmpeg.commandbuidler.CommandAssembly;
import com.yeejoin.amos.ffmpeg.commandbuidler.CommandAssemblyImpl;
import com.yeejoin.amos.ffmpeg.commandbuidler.CommandBuidler;
import com.yeejoin.amos.ffmpeg.data.CommandTasker;
import com.yeejoin.amos.ffmpeg.data.TaskDao;
import com.yeejoin.amos.ffmpeg.data.TaskDaoImpl;
import com.yeejoin.amos.ffmpeg.hander.DefaultOutHandlerMethod;
import com.yeejoin.amos.ffmpeg.hander.KeepAliveHandler;
import com.yeejoin.amos.ffmpeg.hander.OutHandlerMethod;
import com.yeejoin.amos.ffmpeg.hander.TaskHandler;
import com.yeejoin.amos.ffmpeg.hander.TaskHandlerImpl;
/**
* FFmpeg命令操作管理器
*
* @author eguid
* @since jdk1.7
* @version 2017年10月13日
*/
public class CommandManagerImpl implements CommandManager {
/**
* 任务持久化器
*/
private TaskDao taskDao = null;
/**
* 任务执行处理器
*/
private TaskHandler taskHandler = null;
/**
* 命令组装器
*/
private CommandAssembly commandAssembly = null;
/**
* 任务消息处理器
*/
private OutHandlerMethod ohm = null;
/**
* 保活处理器
*/
private KeepAliveHandler keepAliveHandler=null;
/**
* 全部默认初始化,自动查找配置文件
*/
public CommandManagerImpl() {
this(null);
}
/**
* 指定任务池大小的初始化,其他使用默认
* @param size
*/
public CommandManagerImpl(Integer size) {
init(size);
}
/**
* 初始化
* @param taskDao
* @param taskHandler
* @param commandAssembly
* @param ohm
* @param size
*/
public CommandManagerImpl(TaskDao taskDao, TaskHandler taskHandler, CommandAssembly commandAssembly, OutHandlerMethod ohm,Integer size) {
super();
this.taskDao = taskDao;
this.taskHandler = taskHandler;
this.commandAssembly = commandAssembly;
this.ohm = ohm;
init(size);
}
/**
* 初始化,如果几个处理器未注入,则使用默认处理器
*
* @param size
*/
public void init(Integer size) {
if (config == null) {
System.err.println("配置文件加载失败!配置文件不存在或配置错误");
return;
}
boolean iskeepalive=false;
if (size == null) {
size = config.getSize() == null ? 10 : config.getSize();
iskeepalive=config.isKeepalive();
}
if (this.ohm == null) {
this.ohm = new DefaultOutHandlerMethod();
}
if (this.taskDao == null) {
this.taskDao = new TaskDaoImpl(size);
//初始化保活线程
if(iskeepalive) {
keepAliveHandler = new KeepAliveHandler(taskDao);
keepAliveHandler.start();
}
}
if (this.taskHandler == null) {
this.taskHandler = new TaskHandlerImpl(this.ohm);
}
if (this.commandAssembly == null) {
this.commandAssembly = new CommandAssemblyImpl();
}
}
public void setTaskDao(TaskDao taskDao) {
this.taskDao = taskDao;
}
public void setTaskHandler(TaskHandler taskHandler) {
this.taskHandler = taskHandler;
}
public void setCommandAssembly(CommandAssembly commandAssembly) {
this.commandAssembly = commandAssembly;
}
public void setOhm(OutHandlerMethod ohm) {
this.ohm = ohm;
}
/**
* 是否已经初始化
*
* @param 如果未初始化时是否初始化
* @return
*/
public boolean isInit(boolean b) {
boolean ret = this.ohm == null || this.taskDao == null || this.taskHandler == null|| this.commandAssembly == null;
if (ret && b) {
init(null);
}
return ret;
}
@Override
public String start(String id, String command) {
return start(id, command, false);
}
@Override
public String start(String id, String command, boolean hasPath) {
if (isInit(true)) {
System.err.println("执行失败,未进行初始化或初始化失败!");
return null;
}
if (id != null && command != null) {
CommandTasker tasker = taskHandler.process(id, hasPath ? command : config.getPath() + command);
if (tasker != null) {
int ret = taskDao.add(tasker);
if (ret > 0) {
return tasker.getId();
} else {
// 持久化信息失败,停止处理
taskHandler.stop(tasker.getProcess(), tasker.getThread());
if (config.isDebug())
System.err.println("持久化失败,停止任务!");
}
}
}
return null;
}
@Override
public String start(Map<String, String> assembly) {
// ffmpeg环境是否配置正确
if (checkConfig()) {
System.err.println("配置未正确加载,无法执行");
return null;
}
// 参数是否符合要求
if (assembly == null || assembly.isEmpty() || !assembly.containsKey("appName")) {
System.err.println("参数不正确,无法执行");
return null;
}
String appName = (String) assembly.get("appName");
if (appName != null && "".equals(appName.trim())) {
System.err.println("appName不能为空");
return null;
}
assembly.put("ffmpegPath", config.getPath() + "ffmpeg");
//String command = commandAssembly.assembly(assembly);
String command = commandAssembly.assemblyRtsp(assembly);
if (command != null) {
return start(appName, command, true);
}
return null;
}
@Override
public String start(String id,CommandBuidler commandBuidler) {
// ffmpeg环境是否配置正确
if (checkConfig()) {
System.err.println("配置未正确加载,无法执行");
return null;
}
String command =commandBuidler.get();
if (command != null) {
return start(id, command, true);
}
return null;
}
private boolean checkConfig() {
return config == null;
}
@Override
public boolean stop(String id) {
if (id != null && taskDao.isHave(id)) {
if (config.isDebug())
System.out.println("正在停止任务:" + id);
CommandTasker tasker = taskDao.get(id);
if (taskHandler.stop(tasker.getProcess(), tasker.getThread())) {
taskDao.remove(id);
System.out.println("停止任务成功");
return true;
}
}
System.err.println("停止任务失败!id=" + id);
return false;
}
@Override
public int stopAll() {
Collection<CommandTasker> list = taskDao.getAll();
Iterator<CommandTasker> iter = list.iterator();
CommandTasker tasker = null;
int index = 0;
while (iter.hasNext()) {
tasker = iter.next();
if (taskHandler.stop(tasker.getProcess(), tasker.getThread())) {
taskDao.remove(tasker.getId());
index++;
}
}
if (config.isDebug())
System.out.println("停止了" + index + "个任务!");
return index;
}
@Override
public CommandTasker query(String id) {
return taskDao.get(id);
}
@Override
public Collection<CommandTasker> queryAll() {
return taskDao.getAll();
}
@Override
public void destory() {
if(keepAliveHandler!=null) {
//安全停止保活线程
keepAliveHandler.interrupt();
}
}
}
//package com.yeejoin.amos.ffmpeg;
//
//import java.io.BufferedReader;
//import java.io.IOException;
//import java.io.InputStreamReader;
//import java.util.Collection;
//import java.util.HashMap;
//import java.util.List;
//import java.util.Map;
//
//import org.springframework.beans.factory.annotation.Value;
//import org.springframework.boot.CommandLineRunner;
//import org.springframework.core.io.Resource;
//import org.springframework.stereotype.Component;
//
//import com.alibaba.fastjson.JSON;
//import com.yeejoin.amos.entity.App;
//import com.yeejoin.amos.ffmpeg.data.CommandTasker;
//
///**
// * 服务启动时候自动加载摄像头推流
// * @author DELL
// *
// */
//@Component
//public class StartVideoService implements CommandLineRunner{
//
// @Value(value="classpath:cameras.json")
// private Resource resource;
//
//
// @Override
// public void run(String... args) throws Exception {
// List<App> apps = JSON.parseArray(getJSON(), App.class);
// for (App app : apps) {
// sendStream(app);
// }
// System.out.println("------开始加载摄像头推流发方法-----" + apps);
// }
//
// private String getJSON() throws IOException {
// BufferedReader br = new BufferedReader(new InputStreamReader(resource.getInputStream()));
// StringBuffer message=new StringBuffer();
// String line = null;
// while((line = br.readLine()) != null) {
// message.append(line);
// }
// String defaultString=message.toString();
// String result=defaultString.replace("\r\n", "").replaceAll(" +", "");
// return result;
// }
//
// /**
// * 推流
// * @param appName
// * @param input
// * @param output
// * @throws InterruptedException
// */
// public static void sendStream(App app) throws InterruptedException{
// CommandManager manager = new CommandManagerImpl();
// Map<String,String> map = new HashMap<String,String>();
// map.put("appName", app.getAppName());
// map.put("input", app.getInput());
// map.put("output", app.getOutput());
// // 执行任务,id就是appName,如果执行失败返回为null
// String id = manager.start(map);
// System.out.println(id);
// // 通过id查询
// CommandTasker info = manager.query(id);
// System.out.println(info);
// // 查询全部
// Collection<CommandTasker> infoList = manager.queryAll();
// System.out.println(infoList);
// Thread.sleep(30000);
// // 停止id对应的任务
// // manager.stop(id);
// }
//}
package com.yeejoin.amos.ffmpeg.callback;
import com.yeejoin.amos.ffmpeg.data.CommandTasker;
/**
* 事件回调
*
*/
public interface EventCallBack {
/**
* 命令行执行开始事件
* @param t -事件类型
* @param tasker -任务信息
*/
boolean callback(EventCallBackType t,CommandTasker tasker);
}
package com.yeejoin.amos.ffmpeg.callback;
/**
* 事件回调类型
* @author eguid
*
*/
public enum EventCallBackType {
exec,//执行命令后通知
stop,//停止命令后通知
interrupt,//进程中断后通知
heartbeat,//主进程存活心跳
}
package com.yeejoin.amos.ffmpeg.callback.worker;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import com.yeejoin.amos.ffmpeg.CommandManager;
import com.yeejoin.amos.ffmpeg.callback.EventCallBack;
import com.yeejoin.amos.ffmpeg.callback.EventCallBackType;
import com.yeejoin.amos.ffmpeg.data.CommandTasker;
import com.yeejoin.amos.ffmpeg.data.TaskerEventMsg;
/**
*
* 事件消息独立发送线程
*
*/
public class EventMsgNetWorker extends Thread implements EventCallBack{
protected static Queue<TaskerEventMsg> queue = null;// 一个事件消息队列,发送失败的事件消息将会进入队列队尾等待下次再次发送
// 一个网络库,用于快速发送http消息
private int timeout = 300;// 默认300毫秒
public EventMsgNetWorker(int timeout) {
super();
this.timeout = timeout;
queue = new ConcurrentLinkedQueue<>();
}
@Override
public void run() {
for (;;) {
try {
while (queue.peek() != null) {
TaskerEventMsg t = queue.poll();
// 借助网络库发送该消息
String url = CommandManager.config.getCallback();
if (reqGET(url)) {
System.err.println("发送成功");
} else {
System.err.println("发送失败");
// 发送失败的事件消息将会进入队列队尾等待下次再次发送
queue.offer(t);
}
}
} catch (Exception e) {
}
}
}
/**
* 发送get请求
*/
private boolean reqGET(String url) {
URL realUrl;
// PrintWriter out = null;
try {
realUrl = new URL(url);
// 打开和URL之间的连接
URLConnection connection = realUrl.openConnection();
// 设置通用的请求属性
connection.setUseCaches(false);
connection.setConnectTimeout(timeout);
connection.setRequestProperty("accept", "*/*");
connection.setRequestProperty("connection", "Keep-Alive");
connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
connection.setDoOutput(false);
connection.setDoInput(false);
connection.connect();
return true;
} catch (IOException e) {
return false;
}
}
@Override
public boolean callback(EventCallBackType ecbt, CommandTasker tasker) {
return queue.add(new TaskerEventMsg(ecbt, tasker));
}
}
package com.yeejoin.amos.ffmpeg.commandbuidler;
import java.util.Map;
/**
* 命令组装器接口
*/
public interface CommandAssembly {
/**
* 将参数转为ffmpeg命令
* @param paramMap
* @return
*/
public String assembly(Map<String, String> paramMap);
public String assembly();
public String assemblyRtsp(Map<String, String> paramMap);
}
package com.yeejoin.amos.ffmpeg.commandbuidler;
import java.util.Map;
/**
* 默认命令组装器实现
*/
public class CommandAssemblyImpl implements CommandAssembly{
/**
*
* @param map
* -要组装的map
* @param id
* -返回参数:id
* @param id
* -返回参数:组装好的命令
* @return
*/
public String assembly(Map<String, String> paramMap) {
try {
if (paramMap.containsKey("ffmpegPath")) {
String ffmpegPath = (String) paramMap.get("ffmpegPath");
// -i:输入流地址或者文件绝对地址
StringBuilder comm = new StringBuilder(ffmpegPath + " -i ");
// 是否有必输项:输入地址,输出地址,应用名,twoPart:0-推一个元码流;1-推一个自定义推流;2-推两个流(一个是自定义,一个是元码)
if (paramMap.containsKey("input") && paramMap.containsKey("output") && paramMap.containsKey("appName")
&& paramMap.containsKey("twoPart")) {
String input = (String) paramMap.get("input");
String output = (String) paramMap.get("output");
String appName = (String) paramMap.get("appName");
String twoPart = (String) paramMap.get("twoPart");
String codec = (String) paramMap.get("codec");
// 默认h264解码
codec = (codec == null ? "h264" : (String) paramMap.get("codec"));
// 输入地址
comm.append(input);
// 当twoPart为0时,只推一个元码流
if ("0".equals(twoPart)) {
comm.append(" -vcodec " + codec + " -f flv -an " + output + appName);
} else {
// -f :转换格式,默认flv
if (paramMap.containsKey("fmt")) {
String fmt = (String) paramMap.get("fmt");
comm.append(" -f " + fmt);
}
// -r :帧率,默认25;-g :帧间隔
if (paramMap.containsKey("fps")) {
String fps = (String) paramMap.get("fps");
comm.append(" -r " + fps);
comm.append(" -g " + fps);
}
// -s 分辨率 默认是原分辨率
if (paramMap.containsKey("rs")) {
String rs = (String) paramMap.get("rs");
comm.append(" -s " + rs);
}
// 输出地址+发布的应用名
comm.append(" -an " + output + appName);
// 当twoPart为2时推两个流,一个自定义流,一个元码流
if ("2".equals(twoPart)) {
// 一个视频源,可以有多个输出,第二个输出为拷贝源视频输出,不改变视频的各项参数并且命名为应用名+HD
comm.append(" -vcodec copy -f flv -an ").append(output + appName + "HD");
}
}
return comm.toString();
}
}
} catch (Exception e) {
return null;
}
return null;
}
/**
*
* @param map
* -要组装的map
* @param id
* -返回参数:id
* @param id
* -返回参数:组装好的命令
* @return
*/
@Override
public String assemblyRtsp(Map<String, String> paramMap) {
try {
if (paramMap.containsKey("ffmpegPath")) {
String ffmpegPath = (String) paramMap.get("ffmpegPath");
// -i:输入流地址或者文件绝对地址
StringBuilder comm = new StringBuilder(ffmpegPath + " -i ");
// 是否有必输项:输入地址,输出地址,应用名,twoPart:0-推一个元码流;1-推一个自定义推流;2-推两个流(一个是自定义,一个是元码)
//ffmpeg -i 'rtsp://admin:zjt123456@172.16.18.21:554/h264/ch1/main/av_strea' -q 0 -f mpegts -codec:v mpeg1video -s 1366x768 http://127.0.0.1:8081/supersecret/live2
if (paramMap.containsKey("input") && paramMap.containsKey("output") && paramMap.containsKey("appName")
) {
String input = (String) paramMap.get("input");
String output = (String) paramMap.get("output");
String appName = (String) paramMap.get("appName");
comm.append(input);
comm.append(" -q 0 -f mpegts -codec:v mpeg1video -s 1366x768 ");
comm.append(output).append("/");
comm.append(appName);
return comm.toString();
}
}
} catch (Exception e) {
return null;
}
return null;
}
@Override
public String assembly() {
// TODO Auto-generated method stub
return null;
}
}
package com.yeejoin.amos.ffmpeg.commandbuidler;
/**
* 流式命令行构建器
*
*/
public interface CommandBuidler {
/**
* 创建命令行
*
* @param root
* -命令行运行根目录或FFmpeg可执行文件安装目录
* @return
*/
CommandBuidler create(String root);
/**
* 创建默认根目录或默认FFmpeg可执行文件安装目录
*
* @return
*/
CommandBuidler create();
/**
* 累加键-值命令
*
* @param key
* @param val
* @return
*/
CommandBuidler add(String key, String val);
/**
* 累加命令
*
* @param val
* @return
*/
CommandBuidler add(String val);
/**
* 生成完整命令行
*
* @return
*/
CommandBuidler build();
/**
* 获取已经构建好的命令行
* @return
*/
String get();
}
package com.yeejoin.amos.ffmpeg.commandbuidler;
/**
* 默认流式命令构建器工厂类
*
*/
public class CommandBuidlerFactory {
public static CommandBuidler createBuidler() {
return new DefaultCommandBuidler();
};
public static CommandBuidler createBuidler(String rootpath) {
return new DefaultCommandBuidler(rootpath);
};
}
package com.yeejoin.amos.ffmpeg.commandbuidler;
import com.yeejoin.amos.ffmpeg.CommandManager;
/**
* 默认流式命令行构建器(非线程安全)
*/
public class DefaultCommandBuidler implements CommandBuidler{
StringBuilder buidler=null;
String command=null;
public DefaultCommandBuidler() {
create();
}
public DefaultCommandBuidler(String rootpath) {
create(rootpath);
}
@Override
public CommandBuidler create(String rootpath) {
buidler=new StringBuilder(rootpath);
return this;
}
@Override
public CommandBuidler create() {
return create(CommandManager.config.getPath());
}
@Override
public CommandBuidler add(String key, String val) {
return add(key).add(val);
}
@Override
public CommandBuidler add(String val) {
if(buidler!=null) {
buidler.append(val);
addBlankspace();
}
return this;
}
@Override
public CommandBuidler build() {
if(buidler!=null) {
command=buidler.toString();
}
return this;
}
private void addBlankspace() {
buidler.append(" ");
}
@Override
public String get() {
if(command==null) {
build();
}
return command;
}
}
package com.yeejoin.amos.ffmpeg.config;
/**
* 程序基础配置
*
*
*/
public class ProgramConfig {
private String path;//默认命令行执行根路径
private boolean debug;//是否开启debug模式
private Integer size;//任务池大小
private String callback;//回调通知地址
private boolean keepalive;//是否开启保活
//摄像头
private String cameras;
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public boolean isDebug() {
return debug;
}
public void setDebug(boolean debug) {
this.debug = debug;
}
public Integer getSize() {
return size;
}
public void setSize(Integer size) {
this.size = size;
}
public String getCallback() {
return callback;
}
public void setCallback(String callback) {
this.callback = callback;
}
public boolean isKeepalive() {
return keepalive;
}
public void setKeepalive(boolean keepalive) {
this.keepalive = keepalive;
}
public String getCameras() {
return cameras;
}
public void setCameras(String cameras) {
this.cameras = cameras;
}
}
#ffmpeg执行路径,一般为ffmpeg的安装目录,该路径只能是目录,不能为具体文件路径,否则会报错
path=
#是否启用默认的ffmpeg,如果启用默认ffmpeg,上面配置的path就没有用了
defaultpathEnable=true
#存放任务的默认Map的初始化大小
size=10
#事件回调通知接口地址
callback=http://127.0.0.1/callback
#网络超时设置(毫秒)
timeout=300
#开启保活线程
keepalive=true
#是否输出debug消息
debug=true
logging.level.org.springframework.boot.autoconfigure: ERROR
\ No newline at end of file
package com.yeejoin.amos.ffmpeg.data;
import com.yeejoin.amos.ffmpeg.hander.OutHandler;
/**
* 用于存放任务id,任务主进程,任务输出线程
*
* @author eguid
* @since jdk1.7
* @version 2016年10月29日
*/
public class CommandTasker {
private final String id;// 任务id
private final String command;//命令行
private Process process;// 命令行运行主进程
private OutHandler thread;// 命令行消息输出子线程
public CommandTasker(String id,String command) {
this.id = id;
this.command=command;
}
public CommandTasker(String id,String command, Process process, OutHandler thread) {
this.id = id;
this.command=command;
this.process = process;
this.thread = thread;
}
public String getId() {
return id;
}
public Process getProcess() {
return process;
}
public OutHandler getThread() {
return thread;
}
public String getCommand() {
return command;
}
public void setProcess(Process process) {
this.process = process;
}
public void setThread(OutHandler thread) {
this.thread = thread;
}
@Override
public String toString() {
return "CommandTasker [id=" + id + ", command=" + command + ", process=" + process + ", thread=" + thread + "]";
}
}
package com.yeejoin.amos.ffmpeg.data;
import java.util.Collection;
/**
* 任务信息持久层接口
* @author eguid
* @since jdk1.7
* @version 2016年10月29日
*/
public interface TaskDao {
/**
* 通过id查询任务信息
* @param id - 任务ID
* @return CommandTasker -任务实体
*/
public CommandTasker get(String id);
/**
* 查询全部任务信息
* @return Collection<CommandTasker>
*/
public Collection<CommandTasker> getAll();
/**
* 增加任务信息
* @param CommandTasker -任务信息实体
* @return 增加数量:<1-增加失败,>=1-增加成功
*/
public int add(CommandTasker CommandTasker);
/**
* 删除id对应的任务信息
* @param id
* @return 数量:<1-操作失败,>=1-操作成功
*/
public int remove(String id);
/**
* 删除全部任务信息
* @return 数量:<1-操作失败,>=1-操作成功
*/
public int removeAll();
/**
* 是否存在某个ID
* @param id - 任务ID
* @return true:存在,false:不存在
*/
public boolean isHave(String id);
}
package com.yeejoin.amos.ffmpeg.data;
import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
* 任务信息持久层实现
*
* @author eguid
* @since jdk1.7
* @version 2016年10月29日
*/
public class TaskDaoImpl implements TaskDao {
// 存放任务信息
private ConcurrentMap<String, CommandTasker> map = null;
public TaskDaoImpl(int size) {
map = new ConcurrentHashMap<>(size);
}
@Override
public CommandTasker get(String id) {
return map.get(id);
}
@Override
public Collection<CommandTasker> getAll() {
return map.values();
}
@Override
public int add(CommandTasker CommandTasker) {
String id = CommandTasker.getId();
if (id != null && !map.containsKey(id)) {
map.put(CommandTasker.getId(), CommandTasker);
if(map.get(id)!=null)
{
return 1;
}
}
return 0;
}
@Override
public int remove(String id) {
if(map.remove(id) != null){
return 1;
};
return 0;
}
@Override
public int removeAll() {
int size = map.size();
try {
map.clear();
} catch (Exception e) {
return 0;
}
return size;
}
@Override
public boolean isHave(String id) {
return map.containsKey(id);
}
}
package com.yeejoin.amos.ffmpeg.data;
import com.yeejoin.amos.ffmpeg.callback.EventCallBackType;
/**
* 命令行事件消息
* @author eguid
*
*/
public class TaskerEventMsg {
EventCallBackType ecbt;
CommandTasker tasker;
public TaskerEventMsg(EventCallBackType ecbt, CommandTasker tasker) {
super();
this.ecbt = ecbt;
this.tasker = tasker;
}
public EventCallBackType getEcbt() {
return ecbt;
}
public void setEcbt(EventCallBackType ecbt) {
this.ecbt = ecbt;
}
public CommandTasker getTasker() {
return tasker;
}
public void setTasker(CommandTasker tasker) {
this.tasker = tasker;
}
@Override
public String toString() {
return "CommandEventMsg [ecbt=" + ecbt + ", tasker=" + tasker + "]";
}
}
package com.yeejoin.amos.ffmpeg.hander;
/**
* 默认任务消息输出处理
* @author eguid
* @since jdk1.7
* @version 2017年10月13日
*/
public class DefaultOutHandlerMethod implements OutHandlerMethod{
/**
* 任务是否异常中断,如果
*/
public boolean isBroken=false;
@Override
public void parse(String id,String msg) {
//过滤消息
if (msg.indexOf("fail") != -1) {
System.err.println(id + "任务可能发生故障:" + msg);
System.err.println("失败,设置中断状态");
isBroken=true;
}else if(msg.indexOf("miss")!= -1) {
System.err.println(id + "任务可能发生丢包:" + msg);
System.err.println("失败,设置中断状态");
isBroken=true;
}else {
isBroken=false;
System.err.println(id + "消息:" + msg);
}
}
@Override
public boolean isbroken() {
return isBroken;
}
}
package com.yeejoin.amos.ffmpeg.hander;
import java.io.IOException;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import com.yeejoin.amos.ffmpeg.data.CommandTasker;
import com.yeejoin.amos.ffmpeg.data.TaskDao;
import com.yeejoin.amos.ffmpeg.utils.ExecUtil;
/**
* 任务保活处理器(一个后台保活线程,用于处理异常中断的持久任务)
* @author eguid
*
*/
public class KeepAliveHandler extends Thread{
/**待处理队列*/
private static Queue<String> queue=null;
public int err_index=0;//错误计数
public volatile int stop_index=0;//安全停止线程标记
/** 任务持久化器*/
private TaskDao taskDao = null;
public KeepAliveHandler(TaskDao taskDao) {
super();
this.taskDao=taskDao;
queue=new ConcurrentLinkedQueue<>();
}
public static void add(String id ) {
if(queue!=null) {
queue.offer(id);
}
}
public boolean stop(Process process) {
if (process != null) {
process.destroy();
return true;
}
return false;
}
@Override
public void run() {
for(;stop_index==0;) {
if(queue==null) {
continue;
}
String id=null;
CommandTasker task=null;
try {
while(queue.peek() != null) {
System.err.println("准备重启任务:"+queue);
id=queue.poll();
task=taskDao.get(id);
//重启任务
ExecUtil.restart(task);
}
}catch(IOException e) {
System.err.println(id+" 任务重启失败,详情:"+task);
//重启任务失败
err_index++;
}catch(Exception e) {
}
}
}
@Override
public void interrupt() {
stop_index=1;
}
}
package com.yeejoin.amos.ffmpeg.hander;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import com.yeejoin.amos.ffmpeg.CommandManager;
/**
* 任务消息输出处理器
* @author eguid
* @since jdk1.7
* @version 2017年10月13日
*/
public class OutHandler extends Thread {
/**控制状态 */
private volatile boolean desstatus = true;
/**读取输出流*/
private BufferedReader br = null;
/**任务ID*/
private String id = null;
/**消息处理方法*/
private OutHandlerMethod ohm;
/**
* 创建输出线程(默认立即开启线程)
* @param is
* @param id
* @param ohm
* @return
*/
public static OutHandler create(InputStream is, String id,OutHandlerMethod ohm) {
return create(is, id, ohm,true);
}
/**
* 创建输出线程
* @param is
* @param id
* @param ohm
* @param start-是否立即开启线程
* @return
*/
public static OutHandler create(InputStream is, String id,OutHandlerMethod ohm,boolean start) {
OutHandler out= new OutHandler(is, id, ohm);
if(start)
out.start();
return out;
}
public void setOhm(OutHandlerMethod ohm) {
this.ohm = ohm;
}
public void setDesStatus(boolean desStatus) {
this.desstatus = desStatus;
}
public void setId(String id) {
this.id = id;
}
public OutHandlerMethod getOhm() {
return ohm;
}
public OutHandler(InputStream is, String id,OutHandlerMethod ohm) {
br = new BufferedReader(new InputStreamReader(is));
this.id = id;
this.ohm=ohm;
}
/**
* 重写线程销毁方法,安全的关闭线程
*/
@Override
public void destroy() {
setDesStatus(false);
}
/**
* 执行输出线程
*/
@Override
public void run() {
String msg = null;
try {
if (CommandManager.config.isDebug()) {
System.out.println(id + "开始推流!");
}
while (desstatus && (msg = br.readLine()) != null) {
ohm.parse(id,msg);
if(ohm.isbroken()) {
System.err.println("检测到中断,提交重启任务给保活处理器");
//如果发生异常中断,立即进行保活
//把中断的任务交给保活处理器进行进一步处理
KeepAliveHandler.add(id);
}
}
} catch (IOException e) {
System.out.println("发生内部异常错误,自动关闭[" + this.getId() + "]线程");
destroy();
} finally {
if (this.isAlive()) {
destroy();
}
}
}
}
package com.yeejoin.amos.ffmpeg.hander;
/**
* 输出消息处理
* @author eguid
* @since jdk1.7
* @version 2017年10月13日
*/
public interface OutHandlerMethod {
/**
* 解析消息
* @param id-任务ID
* @param msg -消息
*/
public void parse(String id, String msg);
/**
* 任务是否异常中断
* @return
*/
public boolean isbroken();
}
package com.yeejoin.amos.ffmpeg.hander;
import com.yeejoin.amos.ffmpeg.data.CommandTasker;
/**
* 任务执行接口
* @author eguid
* @since jdk1.7
* @version 2016年10月29日
*/
public interface TaskHandler {
/**
* 按照命令执行主进程和输出线程
*
* @param id
* @param command
* @return
*/
public CommandTasker process(String id, String command);
/**
* 停止主进程(停止主进程需要保证输出线程已经关闭,否则输出线程会出错)
*
* @param process
* @return
*/
public boolean stop(Process process);
/**
* 停止输出线程
*
* @param thread
* @return
*/
public boolean stop(Thread thread);
/**
* 正确的停止输出线程和主进程
*
* @param process
* @param thread
* @return
*/
public boolean stop(Process process, Thread thread);
}
package com.yeejoin.amos.ffmpeg.hander;
import java.io.IOException;
import com.yeejoin.amos.ffmpeg.CommandManager;
import com.yeejoin.amos.ffmpeg.data.CommandTasker;
import com.yeejoin.amos.ffmpeg.utils.ExecUtil;
/**
* 任务处理实现
* @author eguid
* @since jdk1.7
* @version 2016年10月29日
*/
public class TaskHandlerImpl implements TaskHandler {
private OutHandlerMethod ohm=null;
public TaskHandlerImpl(OutHandlerMethod ohm) {
this.ohm = ohm;
}
public void setOhm(OutHandlerMethod ohm) {
this.ohm = ohm;
}
@Override
public CommandTasker process(String id, String command) {
CommandTasker tasker = null;
try {
tasker =ExecUtil.createTasker(id,command,ohm);
if(CommandManager.config.isDebug())
System.out.println(id+" 执行命令行:"+command);
return tasker;
} catch (IOException e) {
//运行失败,停止任务
ExecUtil.stop(tasker);
if(CommandManager.config.isDebug())
System.err.println(id+" 执行命令失败!进程和输出线程已停止");
// 出现异常说明开启失败,返回null
return null;
}
}
@Override
public boolean stop(Process process) {
return ExecUtil.stop(process);
}
@Override
public boolean stop(Thread outHandler) {
return ExecUtil.stop(outHandler);
}
@Override
public boolean stop(Process process, Thread thread) {
boolean ret=false;
ret=stop(thread);
ret=stop(process);
return ret;
}
}
package com.yeejoin.amos.ffmpeg.test;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import com.yeejoin.amos.ffmpeg.CommandManager;
import com.yeejoin.amos.ffmpeg.CommandManagerImpl;
import com.yeejoin.amos.ffmpeg.commandbuidler.CommandBuidlerFactory;
import com.yeejoin.amos.ffmpeg.data.CommandTasker;
/**
* 测试
* @author eguid
* @since jdk1.7
* @version 2017年10月13日
*/
public class Test {
/**
* 命令组装器测试
* @throws InterruptedException
*/
public static void test1() throws InterruptedException{
CommandManager manager = new CommandManagerImpl();
Map<String,String> map = new HashMap<String,String>();
map.put("appName", "test123");
map.put("input", "rtsp://admin:zjt123456@172.16.18.20:554/h264/ch1/main/av_stream");
map.put("output", "rtmp://172.16.9.20/live/");
map.put("codec", "h264");
map.put("fmt", "flv");
map.put("fps", "25");
map.put("rs", "640x360");
map.put("twoPart", "2");
// 执行任务,id就是appName,如果执行失败返回为null
String id = manager.start(map);
System.out.println(id);
// 通过id查询
CommandTasker info = manager.query(id);
System.out.println(info);
// 查询全部
Collection<CommandTasker> infoList = manager.queryAll();
System.out.println(infoList);
Thread.sleep(30000);
// 停止id对应的任务
manager.stop(id);
}
/**
* 默认方式,rtsp->rtmp转流单个命令测试
* @throws InterruptedException
*/
public static void test2() throws InterruptedException{
CommandManager manager = new CommandManagerImpl();
// -rtsp_transport tcp
//测试多个任何同时执行和停止情况
//默认方式发布任务
manager.start("tomcat", "ffmpeg -i rtsp://184.72.239.149/vod/mp4://BigBuckBunny_175k.mov -vcodec copy -acodec copy -f flv -y rtmp://106.14.182.20:1935/rtmp/tomcat");
Thread.sleep(30000);
// 停止全部任务
manager.stopAll();
}
/**
* 完整ffmpeg路径测试
* @throws InterruptedException
*/
public static void test4() throws InterruptedException{
CommandManager manager = new CommandManagerImpl();
// -rtsp_transport tcp
//测试多个任何同时执行和停止情况
//默认方式发布任务
manager.start("tomcat", "D:/TestWorkspaces/FFmpegCommandHandler/src/cc/eguid/FFmpegCommandManager/ffmpeg/ffmpeg -i rtsp://184.72.239.149/vod/mp4://BigBuckBunny_175k.mov -vcodec copy -acodec copy -f flv -y rtmp://106.14.182.20:1935/rtmp/tomcat",true);
Thread.sleep(30000);
// 停止全部任务
manager.stopAll();
}
/**
* rtsp-rtmp转流多任务测试
* @throws InterruptedException
*/
public static void test3() throws InterruptedException{
CommandManager manager = new CommandManagerImpl();
// -rtsp_transport tcp
//测试多个任何同时执行和停止情况
//false表示使用配置文件中的ffmpeg路径,true表示本条命令已经包含ffmpeg所在的完整路径
manager.start("tomcat", "ffmpeg -i rtsp://184.72.239.149/vod/mp4://BigBuckBunny_175k.mov -vcodec copy -acodec copy -f flv -y rtmp://106.14.182.20:1935/rtmp/tomcat",false);
manager.start("tomcat1", "ffmpeg -i rtsp://184.72.239.149/vod/mp4://BigBuckBunny_175k.mov -vcodec copy -acodec copy -f flv -y rtmp://106.14.182.20:1935/rtmp/tomcat1",false);
manager.start("tomcat2", "ffmpeg -i rtsp://184.72.239.149/vod/mp4://BigBuckBunny_175k.mov -vcodec copy -acodec copy -f flv -y rtmp://106.14.182.20:1935/rtmp/tomcat2",false);
manager.start("tomcat3", "ffmpeg -i rtsp://184.72.239.149/vod/mp4://BigBuckBunny_175k.mov -vcodec copy -acodec copy -f flv -y rtmp://106.14.182.20:1935/rtmp/tomcat3",false);
manager.start("tomcat4", "ffmpeg -i rtsp://184.72.239.149/vod/mp4://BigBuckBunny_175k.mov -vcodec copy -acodec copy -f flv -y rtmp://106.14.182.20:1935/rtmp/tomcat4",false);
manager.start("tomcat5", "ffmpeg -i rtsp://184.72.239.149/vod/mp4://BigBuckBunny_175k.mov -vcodec copy -acodec copy -f flv -y rtmp://106.14.182.20:1935/rtmp/tomcat5",false);
manager.start("tomcat6", "ffmpeg -i rtsp://184.72.239.149/vod/mp4://BigBuckBunny_175k.mov -vcodec copy -acodec copy -f flv -y rtmp://106.14.182.20:1935/rtmp/tomcat6",false);
manager.start("tomcat7", "ffmpeg -i rtsp://184.72.239.149/vod/mp4://BigBuckBunny_175k.mov -vcodec copy -acodec copy -f flv -y rtmp://106.14.182.20:1935/rtmp/tomcat7",false);
manager.start("tomcat8", "ffmpeg -i rtsp://184.72.239.149/vod/mp4://BigBuckBunny_175k.mov -vcodec copy -acodec copy -f flv -y rtmp://106.14.182.20:1935/rtmp/tomcat8",false);
manager.start("tomcat9", "ffmpeg -i rtsp://184.72.239.149/vod/mp4://BigBuckBunny_175k.mov -vcodec copy -acodec copy -f flv -y rtmp://106.14.182.20:1935/rtmp/tomcat9",false);
Thread.sleep(30000);
// 停止全部任务
manager.stopAll();
}
/**
* 测试流式命令行构建器
* @throws InterruptedException
*/
public static void testStreamCommandAssmbly() throws InterruptedException {
CommandManager manager = new CommandManagerImpl();
manager.start("test1", CommandBuidlerFactory.createBuidler()
.add("ffmpeg").add("-i","rtsp://184.72.239.149/vod/mp4://BigBuckBunny_175k.mov")
.add("-rtsp_transport","tcp")
.add("-vcodec","copy")
.add("-acodec","copy")
.add("-f","flv")
.add("-y").add("rtmp://106.14.182.20:1935/rtmp/test1"));
Thread.sleep(30000);
// 停止全部任务
manager.stopAll();
}
/**
* 测试任务中断自动重启任务
* @throws InterruptedException
*/
public static void testBroken() throws InterruptedException {
CommandManager manager = new CommandManagerImpl();
manager.start("test1", CommandBuidlerFactory.createBuidler()
.add("ffmpeg").add("-i","rtsp://184.72.239.149/vod/mp4://BigBuckBunny_175k.mov")
.add("-rtsp_transport","tcp")
.add("-vcodec","copy")
.add("-acodec","copy")
.add("-f","flv")
.add("-y").add("rtmp://106.14.182.20:1935/rtmp/test1"));
Thread.sleep(30000);
// 停止全部任务
manager.stopAll();
manager.destory();
}
/**
* 批量测试任务中断自动重启任务
* @throws InterruptedException
*/
public static void testBrokenMuti() throws InterruptedException {
CommandManager manager = new CommandManagerImpl();
manager.start("test1", CommandBuidlerFactory.createBuidler()
.add("ffmpeg").add("-i","rtsp://184.72.239.149/vod/mp4://BigBuckBunny_175k.mov")
.add("-rtsp_transport","tcp")
.add("-vcodec","copy")
.add("-acodec","copy")
.add("-f","flv")
.add("-y").add("rtmp://106.14.182.20:1935/rtmp/test1"));
manager.start("test2", CommandBuidlerFactory.createBuidler()
.add("ffmpeg").add("-i","rtsp://184.72.239.149/vod/mp4://BigBuckBunny_175k.mov")
.add("-rtsp_transport","tcp")
.add("-vcodec","copy")
.add("-acodec","copy")
.add("-f","flv")
.add("-y").add("rtmp://106.14.182.20:1935/rtmp/test2"));
manager.start("test3", CommandBuidlerFactory.createBuidler()
.add("ffmpeg").add("-i","rtsp://184.72.239.149/vod/mp4://BigBuckBunny_175k.mov")
.add("-rtsp_transport","tcp")
.add("-vcodec","copy")
.add("-acodec","copy")
.add("-f","flv")
.add("-y").add("rtmp://106.14.182.20:1935/rtmp/test3"));
manager.start("test4", CommandBuidlerFactory.createBuidler()
.add("ffmpeg").add("-i","rtsp://184.72.239.149/vod/mp4://BigBuckBunny_175k.mov")
.add("-rtsp_transport","tcp")
.add("-vcodec","copy")
.add("-acodec","copy")
.add("-f","flv")
.add("-y").add("rtmp://106.14.182.20:1935/rtmp/test4"));
manager.start("test5", CommandBuidlerFactory.createBuidler()
.add("ffmpeg").add("-i","rtsp://184.72.239.149/vod/mp4://BigBuckBunny_175k.mov")
// .add("-rtsp_transport","tcp")
.add("-vcodec","copy")
.add("-acodec","copy")
.add("-f","flv")
.add("-y").add("rtmp://106.14.182.20:1935/rtmp/test5"));
Thread.sleep(30000);
// 停止全部任务
manager.stopAll();
manager.destory();
}
//rtsp输出
public static void test5() throws InterruptedException{
CommandManager manager = new CommandManagerImpl();
Map<String,String> map = new HashMap<String,String>();
map.put("appName", "live1");
map.put("input", "rtsp://admin:zjt123456@172.16.18.20:554/h264/ch1/main/av_stream");
map.put("output", "http://127.0.0.1:8081/supersecret");
// 执行任务,id就是appName,如果执行失败返回为null
String id = manager.start(map);
System.out.println(id);
// 通过id查询
CommandTasker info = manager.query(id);
System.out.println(info);
// 查询全部
Collection<CommandTasker> infoList = manager.queryAll();
System.out.println(infoList);
Thread.sleep(30000);
// 停止id对应的任务
// manager.stop(id);
}
//rtsp输出
public static void test6() throws InterruptedException{
CommandManager manager = new CommandManagerImpl();
Map<String,String> map = new HashMap<String,String>();
map.put("appName", "live2");
map.put("input", "rtsp://admin:zjt123456@172.16.18.21:554/h264/ch1/main/av_stream");
map.put("output", "http://127.0.0.1:8081/supersecret");
// 执行任务,id就是appName,如果执行失败返回为null
String id = manager.start(map);
System.out.println(id);
// 通过id查询
CommandTasker info = manager.query(id);
System.out.println(info);
// 查询全部
Collection<CommandTasker> infoList = manager.queryAll();
System.out.println(infoList);
Thread.sleep(30000);
// 停止id对应的任务
// manager.stop(id);
}
public static void test7() throws InterruptedException{
CommandManager manager = new CommandManagerImpl();
Map<String,String> map = new HashMap<String,String>();
map.put("appName", "live3");
map.put("input", "rtsp://admin:admin123@172.16.10.156:554/h264/ch1/main/av_stream");
map.put("output", "http://127.0.0.1:8081/supersecret");
// 执行任务,id就是appName,如果执行失败返回为null
String id = manager.start(map);
System.out.println(id);
// 通过id查询
CommandTasker info = manager.query(id);
System.out.println(info);
// 查询全部
Collection<CommandTasker> infoList = manager.queryAll();
System.out.println(infoList);
Thread.sleep(30000);
// 停止id对应的任务
// manager.stop(id);
}
public static void main(String[] args) throws InterruptedException {
//test5();
test6();
// test7();
// test2();
// test3();
// test4();
// testStreamCommandAssmbly();
// testBroken();
//testBrokenMuti();
}
}
package com.yeejoin.amos.ffmpeg.utils;
import java.io.File;
import java.util.UUID;
import org.springframework.util.ClassUtils;
/**
* 公共常用方法工具
*
* @author eguid
*
*/
public class CommonUtil {
/**
* 当前项目根路径
*/
public static final String rootPath = getProjectRootPath();
public static final String TRUE = "true";
public static final String NULL_STRING = "";
public static final String H_LINE = "-";
public static String getUUID() {
return UUID.randomUUID().toString().trim().replaceAll(H_LINE, NULL_STRING);
}
/**
* 是否为空
*
* @param str
* @return boolean true:为空,false:不为空
*/
public static boolean isNull(String str) {
return str == null || NULL_STRING.equals(str.trim());
}
/**
* 字符串是否是"true"
*
* @param str
* @return
*/
public static boolean isTrue(String str) {
return TRUE.equals(str) ? true : false;
}
/**
* 获取项目根目录(静态)
*
* @return
*/
public static String getRootPath() {
return rootPath;
}
/**
* 获取项目根目录(动态)
*
* @return
*/
public static String getProjectRootPath() {
String path = null;
try {
path = ClassUtils.getDefaultClassLoader().getResource("").getPath();
} catch (Exception e) {
File directory = new File(NULL_STRING);
path = directory.getAbsolutePath() + File.separator;
}
return path;
}
/**
* 获取类路径
*
* @param cla
* @return
*/
public static String getClassPath(Class<?> cla) {
return cla.getResource("").getPath();
}
}
package com.yeejoin.amos.ffmpeg.utils;
import java.io.IOException;
import com.yeejoin.amos.ffmpeg.data.CommandTasker;
import com.yeejoin.amos.ffmpeg.hander.OutHandler;
import com.yeejoin.amos.ffmpeg.hander.OutHandlerMethod;
/**
* 命令行操作工具类
* @author eguid
*
*/
public class ExecUtil {
/**
* 执行命令行并获取进程
* @param cmd
* @return
* @throws IOException
*/
public static Process exec(String cmd) throws IOException {
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec(cmd);// 执行命令获取主进程
return process;
}
/**
* 销毁进程
* @param process
* @return
*/
public static boolean stop(Process process) {
if (process != null) {
process.destroy();
return true;
}
return false;
}
/**
* 销毁输出线程
* @param outHandler
* @return
*/
public static boolean stop(Thread outHandler) {
if (outHandler != null && outHandler.isAlive()) {
outHandler.stop();
outHandler.destroy();
return true;
}
return false;
}
/**
* 销毁
* @param process
* @param outHandler
*/
public static void stop(CommandTasker tasker) {
if(tasker!=null) {
stop(tasker.getThread());
stop(tasker.getProcess());
}
}
/**
* 创建命令行任务
* @param id
* @param command
* @return
* @throws IOException
*/
public static CommandTasker createTasker(String id,String command,OutHandlerMethod ohm) throws IOException {
// 执行本地命令获取任务主进程
Process process=exec(command);
// 创建输出线程
OutHandler outHandler=OutHandler.create(process.getErrorStream(), id,ohm);
CommandTasker tasker = new CommandTasker(id,command, process, outHandler);
return tasker;
}
/**
* 中断故障缘故重启
* @param tasker
* @return
* @throws IOException
*/
public static CommandTasker restart(CommandTasker tasker) throws IOException {
if(tasker!=null) {
String id=tasker.getId(),command=tasker.getCommand();
OutHandlerMethod ohm=null;
if(tasker.getThread()!=null) {
ohm=tasker.getThread().getOhm();
}
//安全销毁命令行进程和输出子线程
stop(tasker);
// 执行本地命令获取任务主进程
Process process=exec(command);
tasker.setProcess(process);
// 创建输出线程
OutHandler outHandler=OutHandler.create(process.getErrorStream(), id,ohm);
tasker.setThread(outHandler);
}
return tasker;
}
}
package com.yeejoin.amos.ffmpeg.utils;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
/**
* properties配置文件读取
* @author eguid
*
*/
public class PropertiesUtil {
/**
* 加载properties配置文件并读取配置项
* @param path
* @param cl
* @return
*/
@SuppressWarnings("unchecked")
public static <T>T load(String path, Class<T> cl) {
InputStream is = null;
try {
is = getInputStream(path);
} catch (FileNotFoundException e) {
//尝试从web目录读取
String newpath=CommonUtil.getProjectRootPath()+path;
System.err.println("尝试从web目录读取配置文件:"+newpath);
try {
is = getInputStream(newpath);
System.err.println("web目录读取到配置文件:"+newpath);
} catch (FileNotFoundException e1) {
System.err.println("没找到配置文件,读取默认配置文件");
//尝试从jar包中读取默认配置文件
ClassLoader classloader = Thread.currentThread().getContextClassLoader();
try {
is = classloader.getResourceAsStream("com/yeejoin/amos/ffmpeg/config/defaultFFmpegConfig.properties");
System.err.println("读取默认配置文件:defaultFFmpegConfig.properties");
} catch (Exception e2) {
System.err.println("没找到默认配置文件:defaultFFmpegConfig.properties");
return null;
}
}
}
if (is != null) {
Properties pro = new Properties();
try {
System.err.println("加载配置文件...");
pro.load(is);
System.err.println("加载配置文件完毕");
return (T)load(pro, cl);
} catch (IOException e) {
System.err.println("加载配置文件失败");
return null;
}
}
return null;
}
/**
* 读取配置项并转换为对应对象
* @param pro
* @param cl
* @return
*/
public static Object load(Properties pro, Class<?> cl) {
try {
Map<String, Object> map = getMap(pro);
System.err.println("读取的配置项:" + map);
Object obj = ReflectUtil.mapToObj(map, cl);
System.err.println("转换后的对象:" + obj);
return obj;
} catch (InstantiationException e) {
System.err.println("加载配置文件失败");
return null;
} catch (IllegalAccessException e) {
System.err.println("加载配置文件失败");
return null;
} catch (IllegalArgumentException e) {
System.err.println("加载配置文件失败");
return null;
} catch (InvocationTargetException e) {
System.err.println("加载配置文件失败");
return null;
}
}
/**
* 获取对应文件路径下的文件流
* @param path
* @return
* @throws FileNotFoundException
*/
public static InputStream getInputStream(String path) throws FileNotFoundException {
return new FileInputStream(path);
}
/**
* 根据路径获取properties的Map格式内容
* @param path
* @return
*/
public static Map<String, Object> getMap(String path){
Properties pro=new Properties();
try {
pro.load(getInputStream(path));
return getMap(pro);
} catch (IOException e) {
return null;
}
}
/**
* 根据路径获取properties的Map格式内容
* @param path
* @param isRootPath -是否在项目根目录中
* @return
*/
public static Map<String, Object> getMap(String path,boolean isRootPath){
return getMap(isRootPath?CommonUtil.getProjectRootPath()+path:path);
}
/**
* Properties配置项转为Map<String, Object>
* @param pro
* @return
*/
public static Map<String, Object> getMap(Properties pro) {
if (pro == null || pro.isEmpty() || pro.size() < 1) {
return null;
}
Map<String, Object> map = new HashMap<String, Object>();
for (Entry<Object, Object> en : pro.entrySet()) {
String key = (String) en.getKey();
Object value = en.getValue();
map.put(key, value);
}
return map;
}
}
package com.yeejoin.amos.ffmpeg.utils;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
/**
* 反射操作工具
*
* @author eguid
*
*/
public class ReflectUtil {
public static final String SET = "set";
public static final String GET = "get";
public static Object mapToObj(Map<String, Object> map, Class<?> oc)
throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Method[] ms = oc.getDeclaredMethods();
if (ms == null || ms.length < 1) {
return null;
}
Object obj = getObject(oc);
for (Method m : ms) {
String methodName = m.getName();
String fieldName = getMethodField(methodName, SET);
Object value = map.get(fieldName);
if (value != null) {
setMethodValue(m, obj, typeConvert(value, m));
}
}
return obj;
}
public static Object typeConvert(Object obj, Method m) {
return typeConvert(obj, m.getParameterTypes()[0].getName());
}
public static Object typeConvert(Object obj, Field f) {
return typeConvert(obj, f.getType().getName());
}
/**
* 基础数据转换
* @param obj
* @param typeName
* @return
*/
public static Object typeConvert(Object obj, String typeName) {
// 基础数据都可以转为String
String str = String.valueOf(obj);
if ("int".equals(typeName) || "java.lang.Integer".equals(typeName)) {
return Integer.valueOf(str.trim());
} else if ("long".equals(typeName) || "java.lang.Long".equals(typeName)) {
return Long.valueOf(str.trim());
} else if ("byte".equals(typeName) || "java.lang.Byte".equals(typeName)) {
return Byte.valueOf(str.trim());
} else if ("short".equals(typeName) || "java.lang.Short".equals(typeName)) {
return Short.valueOf(str.trim());
} else if ("float".equals(typeName) || "java.lang.Float".equals(typeName)) {
return Float.valueOf(str.trim());
} else if ("double".equals(typeName) || "java.lang.Double".equals(typeName)) {
return Double.valueOf(str.trim());
} else if ("boolean".equals(typeName) || "java.lang.Boolean".equals(typeName)) {
return CommonUtil.TRUE.equals(str)?true:false;
} else if ("char".equals(typeName) || "java.lang.Character".equals(typeName)) {
return Character.valueOf(str.trim().charAt(0));
} else if ("java.lang.String".equals(typeName)) {
return str;
}
return null;
}
public static Class<?> getFieldType(Class<?> cl, String fieldName) throws NoSuchFieldException, SecurityException {
Field f = cl.getDeclaredField(fieldName);
return f.getType();
}
public static Field findField(Class<?> cl, String fieldName) throws NoSuchFieldException, SecurityException {
return cl.getDeclaredField(fieldName);
}
/**
* 执行方法
*
* @param m
* - 方法
* @param obj
* - 对象
* @param value
* - 参数
* @throws IllegalAccessException
* @throws IllegalArgumentException
* @throws InvocationTargetException
*/
public static Object setMethodValue(Method m, Object obj, Object... value)
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
m.getParameterTypes();
return m.invoke(obj, value);
}
public static Object getFieldValue(Class<?> obj, String FieldName) throws NoSuchFieldException, SecurityException {
return obj.getDeclaredField(FieldName);
}
/**
* 通过class实例化
*
* @param oc
* @return
* @throws InstantiationException
* @throws IllegalAccessException
*/
public static Object getObject(Class<?> oc) throws InstantiationException, IllegalAccessException {
return oc.newInstance();
}
/**
* 获取方法字段
*
* @param methodName
* @param prefix
* @param lowercase
* @return
*/
public static String getMethodField(String methodName, String prefix) {
String m = null;
if (prefix != null) {
if (methodName.indexOf(prefix) >= 0) {
m = methodName.substring(prefix.length());
return stringFirstLower(m);
}
}
return m;
}
/**
* 首字母大写
*
* @param str
* @return
*/
public static String stringFirstUpper(String str) {
char[] ch = str.toCharArray();
if (ch[0] >= 'a' && ch[0] <= 'z') {
ch[0] = (char) (ch[0] - 32);
}
return new String(ch);
}
/**
* 首字母小写
*
* @param str
* @return
*/
public static String stringFirstLower(String str) {
char[] ch = str.toCharArray();
if (ch[0] >= 'A' && ch[0] <= 'Z') {
ch[0] = (char) (ch[0] + 32);
}
return new String(ch);
}
}
package com.yeejoin.amos.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import com.yeejoin.amos.entity.Video;
@Repository
public interface VideoMapper {
public Integer getCount(@Param("name") String name, @Param("parentId") Long parentId);
public List<Video> findPageList( @Param("offset")Integer offset,@Param("pageSize") Integer pageSize,@Param("name") String name, @Param("parentId") Long parentId);
/**
* 根据楼层查询摄像头
* @param floor3d
* @return
*/
public List<Video> findAll(@Param("floor3d") String floor3d);
List<Video> selectByParentId();
void insertVideo(Video video);
void deleteVideo(@Param("token") String token);
Video selectByToken(@Param("token") String token);
void updateVideo(Video video);
}
package com.yeejoin.amos.response;
import java.io.Serializable;
public class CommonResponse implements Serializable
{
private static final long serialVersionUID = -8737351878134480646L;
private String result;
private Object dataList;
private String message;
public CommonResponse() {
}
public CommonResponse(final String result) {
this.result = result;
}
public CommonResponse(final Object dataList) {
this.dataList = dataList;
this.result = "";
}
public CommonResponse(final String result, final Object dataList) {
this.dataList = dataList;
this.result = result;
}
public CommonResponse(final String result, final String message) {
this.result = result;
this.message = message;
}
public CommonResponse(final String result, final Object dataList, final String message) {
this.dataList = dataList;
this.result = result;
this.message = message;
}
public Boolean isSuccess() {
return "SUCCESS".equals(this.getResult());
}
public String getResult() {
return this.result;
}
public void setResult(final String result) {
this.result = result;
}
public String getMessage() {
return this.message;
}
public void setMessage(final String message) {
this.message = message;
}
public Object getDataList() {
return this.dataList;
}
public void setDataList(final Object dataList) {
this.dataList = dataList;
}
}
package com.yeejoin.amos.rtsp;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.socket.BinaryMessage;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.BinaryWebSocketHandler;
import java.util.HashMap;
import java.util.List;
@Component
public class HandleRtpWebSocker implements IHandleWebSocket {
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
System.out.println("Rtp Sesson start:" + session.getId());
System.out.println(session.getAcceptedProtocol());
}
@Override
public void handleTextMessage(WebSocketSession session, TextMessage message) {
SessionInfo sessionInfo = SessionInfo.get(session.getId());
if(sessionInfo == null) {
String str_msg = message.getPayload();
System.out.println("Recv from RTP session:[" + session.getId() + "]\r\n" + str_msg);
List<String> lines = Utils.msg2lines(str_msg);
HashMap<String,String> hsmpVal = Utils.list2key(lines, ":", 1);
String channel = hsmpVal.get("channel".toLowerCase());
String seq = hsmpVal.get("seq".toLowerCase());
try {
if(!StringUtils.isEmpty(channel))
{
String rtspChannel = channel.trim().substring(channel.indexOf(" ")).trim();
sessionInfo = SessionInfo.getByChannel(rtspChannel);
if(sessionInfo == null) {
session.sendMessage(new TextMessage("UNKNOWN\r\n\r\n"));
return;
} else {
SessionInfo.add(session.getId(),sessionInfo);
sessionInfo.getLocalRtspService().attachRtpChannel(session);
String s = WebSocketConfig.PROXY_PROTOCOL + "/" + WebSocketConfig.PROXY_VERSION + " 200 OK" + "\r\n"
+ "seq: " + seq + "\r\n"
+ "\r\n";
session.sendMessage(new TextMessage(s));
System.out.println("[Send to RTP Channel]\r\n" + s);
return;
}
}
session.sendMessage(new TextMessage("ERROR\r\n\r\n"));
} catch (Exception e) {
}
return;
} else {
try {
//sessionInfo.getTcpTask().send(null);
} catch (Exception e) {
e.printStackTrace();
sessionInfo.close();
}
}
}
@Override
public void handleBinaryMessage(WebSocketSession session, BinaryMessage message) {
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
SessionInfo sessionInfo = SessionInfo.get(session.getId());
if(sessionInfo != null) {
SessionInfo.remove(session.getId());
System.out.println("RTP Sesson closed:" + session.getId());
}
}
}
package com.yeejoin.amos.rtsp;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.socket.BinaryMessage;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.List;
@Component
public class HandleRtspWebSocker implements IHandleWebSocket {
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
System.out.println("Rtsp Sesson start:" + session.getId());
}
@Override
public void handleBinaryMessage(WebSocketSession session, BinaryMessage message) {
ByteBuffer bb = message.getPayload();
byte[] data = bb.array();
System.out.println("Recv from RTP session:[" + session.getId() + "]\r\n" + new String(data));
}
@Override
public void handleTextMessage(WebSocketSession session, TextMessage message) {
try {
String str_msg = message.getPayload();
System.out.println("Recv from RTSP session:[" + session.getId() + "]\r\n" + str_msg);
SessionInfo sessionInfo = SessionInfo.get(session.getId());
if (sessionInfo == null) {
List<String> lines = Utils.msg2lines(str_msg);
HashMap<String, String> hsmpVal = Utils.list2key(lines, ":", 1);
String host = hsmpVal.get("host".toLowerCase());
String sport = hsmpVal.get("port".toLowerCase());
String url = hsmpVal.get("url".toLowerCase());
String seq = hsmpVal.get("seq".toLowerCase());
if (StringUtils.isEmpty(host) || StringUtils.isEmpty(sport)) {
session.sendMessage(new TextMessage("UNKNOWN\r\n\r\n"));
return;
}
int port = Integer.parseInt(sport);
sessionInfo = new SessionInfo();
sessionInfo.setHost(host);
sessionInfo.setPort(port);
sessionInfo.setUrl(url);
SessionInfo.add(session.getId(), sessionInfo);
sessionInfo.setLocalRtspService(new LocalRtspService((sessionInfo)));
sessionInfo.setRemoteRtspService(new RemoteRtspService(sessionInfo));
sessionInfo.getLocalRtspService().attachRtspChannel(session);
sessionInfo.getRemoteRtspService().start();
sessionInfo.getLocalRtspService().start();
String channel = sessionInfo.getChannel();
String channelStr = "localhost-" + channel + " " + channel;
String s = WebSocketConfig.PROXY_PROTOCOL + "/" + WebSocketConfig.PROXY_VERSION + " 200 OK" + "\r\n"
+ "channel: " + channelStr + "\r\n"
+ "seq: " + seq + "\r\n"
+ "\r\n";
session.sendMessage(new TextMessage(s));
System.out.println("[Send to RTSP Channel]\r\n" + s);
return;
} else {
sessionInfo.getLocalRtspService().recvMsg(str_msg);
}
} catch(Exception e) {
}
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
SessionInfo sessionInfo = SessionInfo.get(session.getId());
if(sessionInfo != null) {
SessionInfo.remove(session.getId());
sessionInfo.close();
System.out.println("RTSP Sesson closed:" + session.getId());
}
}
}
package com.yeejoin.amos.rtsp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.socket.BinaryMessage;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import java.util.HashMap;
import java.util.List;
@Component
public class HandleWebSocker {
@Autowired
HandleRtpWebSocker handleRtpWebSocker;
@Autowired
HandleRtspWebSocker handleRtspWebSocker;
IHandleWebSocket getHandleWebSocket(WebSocketSession session) {
String secWebSocketProtocol = session.getHandshakeHeaders().getFirst("Sec-WebSocket-Protocol");
if(StringUtils.isEmpty(secWebSocketProtocol)) secWebSocketProtocol = session.getHandshakeHeaders().getFirst("sec-websocket-protocol");
if("control".equalsIgnoreCase(secWebSocketProtocol)) return handleRtspWebSocker;
if("data".equalsIgnoreCase(secWebSocketProtocol)) return handleRtpWebSocker;
return null;
}
void afterConnectionEstablished(WebSocketSession session) throws Exception {
IHandleWebSocket handleWebSocket = getHandleWebSocket(session);
if(handleWebSocket != null) {
handleWebSocket.afterConnectionEstablished(session);
}
}
void handleTextMessage(WebSocketSession session, TextMessage message) {
IHandleWebSocket handleWebSocket = getHandleWebSocket(session);
if(handleWebSocket != null) {
handleWebSocket.handleTextMessage(session,message);
}
}
void handleBinaryMessage(WebSocketSession session, BinaryMessage message) {
IHandleWebSocket handleWebSocket = getHandleWebSocket(session);
if(handleWebSocket != null) {
handleWebSocket.handleBinaryMessage(session,message);
}
}
void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
IHandleWebSocket handleWebSocket = getHandleWebSocket(session);
if(handleWebSocket != null) {
handleWebSocket.afterConnectionClosed(session,status);
}
}
}
package com.yeejoin.amos.rtsp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.socket.BinaryMessage;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.AbstractWebSocketHandler;
import org.springframework.web.socket.handler.BinaryWebSocketHandler;
import java.util.HashMap;
import java.util.List;
@Component
public class HtmlRtspPlayerWebSockerServer extends AbstractWebSocketHandler {
@Autowired
HandleWebSocker handleWebSocker;
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
super.afterConnectionEstablished(session);
handleWebSocker.afterConnectionEstablished(session);
}
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) {
handleWebSocker.handleTextMessage(session,message);
}
@Override
protected void handleBinaryMessage(WebSocketSession session, BinaryMessage message) {
handleWebSocker.handleBinaryMessage(session,message);
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
handleWebSocker.afterConnectionClosed(session,status);
super.afterConnectionClosed(session, status);
}
}
package com.yeejoin.amos.rtsp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.BinaryMessage;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
public interface IHandleWebSocket {
void afterConnectionEstablished(WebSocketSession session) throws Exception;
void handleTextMessage(WebSocketSession session, TextMessage message);
void handleBinaryMessage(WebSocketSession session, BinaryMessage message);
void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception;
}
package com.yeejoin.amos.rtsp;
import org.springframework.util.StringUtils;
import org.springframework.web.socket.BinaryMessage;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
public class LocalRtspService {
private static final String NULL_STRING = "";
private static final byte[] NULL_BYTE = {};
private BlockingQueue<String> queueRtspEvent = new LinkedBlockingDeque<String>();
private BlockingQueue<byte[]> queueRtpEvent = new LinkedBlockingDeque<byte[]>();
private SessionInfo sessionInfo = null;
private RtspSendThread rtspSendThread = null;
private RtpSendThread rtpSendThread = null;
private WebSocketSession rtspSession = null;
private WebSocketSession rtpSession = null;
private HashMap<String,String> hsmpCseq2Seq = new HashMap<String,String>();
public LocalRtspService(SessionInfo sessionInfo) {
this.sessionInfo = sessionInfo;
}
public void start() {
}
public void attachRtspChannel(WebSocketSession rtspSession) {
this.rtspSession = rtspSession;
if(rtspSendThread == null && rtspSession!= null) {
rtspSendThread = new RtspSendThread();
rtspSendThread.start();
}
}
public void attachRtpChannel(WebSocketSession rtpSession) {
this.rtpSession = rtpSession;
if(rtpSendThread == null && rtpSession != null) {
rtpSendThread = new RtpSendThread();
rtpSendThread.start();
}
}
public void close() {
try {
queueRtspEvent.put(NULL_STRING);
queueRtpEvent.put(NULL_BYTE);
} catch(Exception e) {
} }
private class RtspSendThread extends Thread {
public void run() {
try {
String msg;
while((msg = queueRtspEvent.take()) != null) {
if(msg == NULL_STRING)
break;
String head = "";
List<String> lines = Utils.msg2lines(msg);
HashMap<String,String> hsmpVal = Utils.list2key(lines, ":", 1);
String cseq = hsmpVal.get("cseq".toLowerCase());
if(!StringUtils.isEmpty(cseq)) {
String seq = null;
synchronized (hsmpCseq2Seq) {
seq = hsmpCseq2Seq.get(cseq);
hsmpCseq2Seq.remove(cseq);
}
if (seq != null) {
int contentLength = msg.getBytes().length;
head = WebSocketConfig.PROXY_PROTOCOL + "/" + WebSocketConfig.PROXY_VERSION + " 200 OK" + "\r\n"
+ "seq: " + seq + "\r\n"
+ "contentLength: " + contentLength + "\r\n"
+ "\r\n";
}
rtspSession.sendMessage(new TextMessage(head + msg));
System.out.println("[Send to RTSP Channel]--" + rtspSession.getId() + "==============================\r\n" + head + msg);
}
}
} catch(Exception e) {
e.printStackTrace();
}
System.out.println("RtspSendThread is down!");
}
}
public class RtpSendThread extends Thread {
public void run() {
try {
byte[] data;
while((data = queueRtpEvent.take()) != null) {
if(data == NULL_BYTE)
break;
rtpSession.sendMessage(new BinaryMessage(data));
}
} catch(Exception e) {
e.printStackTrace();
}
System.out.println("RtpSendThread is down!");
}
}
private String send_msg = "";
public void recvMsg(String msg) {
send_msg += msg;
int div;
while((div = send_msg.indexOf("\r\n\r\n")) > 0) {
div += 4;
String header = send_msg.substring(0,div).trim();
String body = send_msg.substring(div);
if(!header.startsWith(WebSocketConfig.PROXY_PROTOCOL + "/" + WebSocketConfig.PROXY_VERSION)) {
send_msg = body;
break;
}
List<String> lines = Utils.msg2lines(header);
HashMap<String,String> hsmpVal = Utils.list2key(lines, ":", 1);
String seq = hsmpVal.get("seq".toLowerCase());
String contentLength = hsmpVal.get("contentLength".toLowerCase());
if(!StringUtils.isEmpty(contentLength)) {
int expectLen = Integer.parseInt(contentLength);
byte[] bodyBytes = body.getBytes();
if(expectLen < bodyBytes.length)
return;
String rtspMsg = new String(bodyBytes,0,expectLen);
if(expectLen == bodyBytes.length) {
send_msg = "";
} else {
send_msg = new String(bodyBytes,expectLen,bodyBytes.length - expectLen);
}
lines = Utils.msg2lines(rtspMsg);
hsmpVal = Utils.list2key(lines, ":", 1);
String cseq = hsmpVal.get("cseq".toLowerCase());
if(!StringUtils.isEmpty(seq) && !StringUtils.isEmpty(cseq)) {
synchronized (hsmpCseq2Seq) {
hsmpCseq2Seq.put(cseq, seq);
}
}
sessionInfo.getRemoteRtspService().sendMsg(rtspMsg);
}
}
}
public void sendMsg(String msg) {
if(!msg.startsWith("RTSP")) {
System.out.println("=========================================[ERROR]" + msg.length() + "================================");
}
try {
queueRtspEvent.put(msg);
} catch(Exception e) {
}
}
public void sendData(byte[] data) {
try {
queueRtpEvent.put(data);
} catch(Exception e) {
}
}
public void sendData(byte[] data, int offset, int len) {
if(len == 0) return;
byte[] newData = new byte[len];
System.arraycopy(data,offset,newData,0,len);
sendData(newData);
}
}
package com.yeejoin.amos.rtsp;
import org.springframework.util.StringUtils;
import java.io.InputStream;
import java.net.Socket;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
public class RemoteRtspService {
private final static byte[] RES_HEAD = "RTSP/1.0 200 OK\r\n".getBytes();
private final static String[] OP_NAME = {
"OPTIONS",
"DESCRIBE",
"SETUP",
"PLAY",
"PAUSE",
"ANNOUNCE",
"RECORD",
"GET_PARAMETER",
"TEARDOWN",
};
private SessionInfo sessionInfo = null;
private Socket socket;
private HashMap<String,String> hsmpRtspMsg = new HashMap<String,String>();
private BlockingQueue<EventItem> queueEvent = new LinkedBlockingDeque<EventItem>();
public RemoteRtspService(SessionInfo sessionInfo) {
this.sessionInfo = sessionInfo;
}
public void start() {
(new ExecThread()).start();
}
public void close() {
try {
EventItem eventItem = new EventItem();
eventItem.eventType = EventItem.EVT_STOP_ALL;
queueEvent.put(eventItem);
} catch(Exception ee) {
}
}
public void sendMsg(String msg) {
try {
EventItem eventItem = new EventItem();
eventItem.eventType = EventItem.EVT_SEND_DATA;
eventItem.msg = msg;
queueEvent.put(eventItem);
}catch(Exception e) {
}
}
public void recvMsg(String msg) {
sessionInfo.getLocalRtspService().sendMsg(msg);
}
public void recvData(byte[] data) {
sessionInfo.getLocalRtspService().sendData(data,0,data.length);
}
private boolean connect(String host, int port) {
try {
Socket socket = new Socket(host, port);
this.socket = socket;
sessionInfo.setPort(port);
sessionInfo.setHost(host);
(new RecvThread(socket)).start();
return true;
} catch(Exception e) {
}
return false;
}
private boolean isConnected() {
return (socket != null);
}
private static class EventItem {
public final static int EVT_RECV_MSG = 0;
public final static int EVT_SEND_DATA = 1;
public final static int EVT_STOP_ALL = 2;
public final static int EVT_STOP = 9;
int eventType = EVT_RECV_MSG;
String msg = null;
byte[] data = null;
String opName = null;
Socket socket = null;
}
private class RecvThread extends Thread {
private static final int DATA_UNK = -1;
private static final int DATA_RTSP = 0;
private static final int DATA_RTP = 1;
private Socket socket;
private boolean isTerminated = false;
public RecvThread(Socket socket) {
this.socket = socket;
}
public void run() {
byte[] data = new byte[8192];
int len;
InputStream inputStream = null;
byte[] buff = new byte[16384];
int buffLen = 0;
int dataType = DATA_UNK;
int rtpDateLen = 0;
int expectMsgDataLen = 0;
try {
inputStream = socket.getInputStream();
while ((len = inputStream.read(data)) > 0) {
int offset = 0;
while(offset < len) {
switch (dataType) {
case DATA_UNK: {
boolean isFound = false;
for (int i = offset; i < len; i++) {
if (data[i] != '$' && data[i] != 'R')
continue;
offset = i;
isFound = true;
break;
}
if (isFound) {
buffLen = 0;
expectMsgDataLen = 0;
if(data[offset] == '$')
{
dataType = DATA_RTP;
} else {
dataType = DATA_RTSP;
}
}
break;
}
case DATA_RTP: {
if(buffLen < 4) {
int minLen = Math.min(len - offset, 4 - buffLen);
System.arraycopy(data,offset,buff,buffLen,minLen);
buffLen += minLen;
offset += minLen;
}
if(buffLen < 4)
break;
rtpDateLen = (buff[3] & 0x0FF) + (buff[2] & 0xFF) * 0x100;
if(rtpDateLen < 0) {
System.out.println("Error data");
}
if(rtpDateLen > (buff.length - 4)) {
//Adjust buff size
byte[] newBuff = new byte[buff.length + 16384];
System.arraycopy(buff,0,newBuff,0,buffLen);
buff = newBuff;
}
int minLen = Math.min(rtpDateLen - (buffLen - 4),len - offset);
if(minLen > 0) {
System.arraycopy(data,offset,buff,buffLen,minLen);
offset += minLen;
buffLen += minLen;
} else {
System.out.println("Error data");
}
if(rtpDateLen == (buffLen - 4)) {
byte[] d = new byte[buffLen];
System.arraycopy(buff,0,d,0,buffLen);
recvData(d);
buffLen = 0;
dataType = DATA_UNK;
}
break;
}
case DATA_RTSP: {
if(buffLen < 4) {
int minLen = Math.min(len - offset, 4 - buffLen);
System.arraycopy(data,offset,buff,buffLen,minLen);
buffLen += minLen;
offset += minLen;
expectMsgDataLen = 0;
}
if(buffLen < 4)
break;
if((buff.length - buffLen) < 8192) {
//Adjust buff size
byte[] newBuff = new byte[((int)((buff.length + 16384)/16384)) * 16384];
System.arraycopy(buff,0,newBuff,0,buffLen);
buff = newBuff;
}
for(int i=offset;i<len;i++) {
if(buff.length == buffLen)
break;
buff[buffLen] = data[i];
buffLen ++;
offset ++;
if(expectMsgDataLen == 0) {
if (data[i] == '\n') {
if (buff[ buffLen - 1] == '\n'
&& buff[buffLen - 2] == '\r'
&& buff[buffLen - 3] == '\n'
&& buff[buffLen - 4] == '\r') {
String msg = new String(buff, 0, buffLen);
int div_first = msg.indexOf("\r\n\r\n");
if (div_first < 0) {
continue;
}
List<String> lines = Utils.msg2lines(msg.substring(0, div_first));
HashMap<String, String> hsmpVal = Utils.list2key(lines, ":", 1);
String content_length = hsmpVal.get("Content-Length".toLowerCase());
int contentLength = 0;
if (!StringUtils.isEmpty(content_length)) {
contentLength = Integer.parseInt(content_length.trim());
}
expectMsgDataLen = buffLen + contentLength;
}
}
}
if(expectMsgDataLen > 0) {
if(expectMsgDataLen == buffLen) {
String msg = new String(buff, 0, buffLen);
EventItem newEventItem = new EventItem();
newEventItem.msg = msg;
newEventItem.eventType = EventItem.EVT_RECV_MSG;
queueEvent.put(newEventItem);
expectMsgDataLen = 0;
buffLen = 0;
dataType = DATA_UNK;
break;
}
}
}
break;
}
}
}
}
} catch(Exception e) {
}
try {
if(inputStream != null)
inputStream.close();
} catch(Exception e) {
}
inputStream = null;
System.out.println("RemoteRecvThread Is Down!");
try {
EventItem eventItem = new EventItem();
eventItem.eventType = EventItem.EVT_STOP;
eventItem.socket = socket;
queueEvent.put(eventItem);
} catch(Exception e) {
}
}
}
private class ExecThread extends Thread {
public void run() {
EventItem eventItem;
String sendmsg = "";
try {
while((eventItem = queueEvent.take()) != null) {
switch(eventItem.eventType) {
case EventItem.EVT_RECV_MSG:
{
//1.如果是重定向,则重连socket
//2.将url恢复成原url
String rtspMsg = eventItem.msg;
System.out.println("[Recv From Remote]==================================================\r\n" + rtspMsg);
int div_first = rtspMsg.indexOf("\r\n\r\n");
if (div_first < 0) {
break;
}
List<String> lines = Utils.msg2lines(rtspMsg.substring(0,div_first));
HashMap<String, String> hsmpVal = Utils.list2key(lines, ":", 1);
String cseq = hsmpVal.get("CSeq".toLowerCase());
String rtspReq = null;
if(!StringUtils.isEmpty(cseq)) {
rtspReq = hsmpRtspMsg.get(cseq);
hsmpRtspMsg.remove(cseq);
}
if(lines.get(0).toLowerCase().matches(".+ moved([ ]+)temporarily([ ].*)*")) {
String redirectUrl = hsmpVal.get("Location".toLowerCase());
if(!StringUtils.isEmpty(redirectUrl)) {
redirectUrl = redirectUrl.trim();
HashMap<String,String> hsmpUrl = Utils.parseUrl(redirectUrl);
if(StringUtils.isEmpty(hsmpVal.get("host"))) hsmpVal.put("host","127.0.0.1");
try {
EventItem newEventItem = new EventItem();
newEventItem.eventType = EventItem.EVT_STOP;
newEventItem.socket = socket;
queueEvent.put(newEventItem);
} catch(Exception e) {
}
System.out.println("Redirect to new url:" + redirectUrl + "*******************************************");
if(connect(hsmpUrl.get("host"),Integer.parseInt(hsmpUrl.get("port")))) {
sessionInfo.setRedirectUrl(redirectUrl);
if(rtspReq != null) {
EventItem newEventItem = new EventItem();
newEventItem.eventType = EventItem.EVT_SEND_DATA;
newEventItem.msg = rtspReq;
queueEvent.put(newEventItem);
}
} else {
EventItem newEventItem = new EventItem();
newEventItem.eventType = EventItem.EVT_STOP_ALL;
queueEvent.put(newEventItem);
}
break;
}
} else {
String newUrl = sessionInfo.getRedirectUrl();
if(newUrl != null) {
String oldUrl = sessionInfo.getUrl();
if(newUrl.endsWith("/")) newUrl = newUrl.substring(0,newUrl.length() - 1);
if(oldUrl.endsWith("/")) oldUrl = oldUrl.substring(0,oldUrl.length() - 1);
int idx;
while((idx = rtspMsg.indexOf(newUrl)) >= 0) {
rtspMsg = rtspMsg.substring(0,idx) + oldUrl + rtspMsg.substring(idx + newUrl.length());
}
}
recvMsg(rtspMsg);
}
}
break;
case EventItem.EVT_SEND_DATA:
{
String msg = sendmsg + eventItem.msg;
if(sendmsg.length() < 2) {
msg = StringUtils.trimLeadingWhitespace(msg);
}
sendmsg = msg;
while(true) {
msg = sendmsg;
int div_first = msg.indexOf("\r\n\r\n");
if (div_first <= 0) {
break;
}
List<String> lines = Utils.msg2lines(msg);
HashMap<String, String> hsmpVal = Utils.list2key(lines, ":", 1);
String content_length = hsmpVal.get("Content-Length".toLowerCase());
int contentLength = 0;
if (!StringUtils.isEmpty(content_length)) {
contentLength = Integer.parseInt(content_length.trim());
}
int tailLength = msg.length() - div_first - 4;
if (tailLength < contentLength) {
break;
}
int msgEndIdx = div_first + 4 + contentLength;
sendmsg = msg.substring(msgEndIdx);
String rtspMsg = msg.substring(0, msgEndIdx);
String cseq = hsmpVal.get("CSeq".toLowerCase());
if(!StringUtils.isEmpty(cseq)) hsmpRtspMsg.put(cseq,rtspMsg);
String opName = null;
String firstKey = rtspMsg.trim().split(" ")[0].toUpperCase();
for (String s : OP_NAME) {
if (firstKey.equalsIgnoreCase(s)) {
opName = s;
break;
}
}
if (opName != null) {
if(sessionInfo.getUrl() == null) {
String s = lines.get(0).trim();
int idx = s.indexOf("rtsp://");
if (idx > 0) {
String url = s.substring(idx).split(" ")[0];
HashMap<String, String> hsmpUrl = Utils.parseUrl(url);
if (hsmpUrl != null) {
if (StringUtils.isEmpty(hsmpUrl.get("host")))
hsmpUrl.put("host", "127.0.0.1");
sessionInfo.setHost(hsmpUrl.get("host"));
sessionInfo.setPort(Integer.parseInt(hsmpUrl.get("port")));
sessionInfo.setUrl(url);
}
}
}
if (!isConnected()) {
if (!StringUtils.isEmpty(sessionInfo.getHost()) && sessionInfo.getPort() > 0) {
connect(sessionInfo.getHost(), sessionInfo.getPort());
}
}
if(!isConnected()) {
if (opName.equalsIgnoreCase("OPTIONS")) {
String respMsg = "RTSP/1.0 200 OK\r\n" +
"CSeq: " + cseq + "\r\n" +
"Server: Wowza Streaming Engine 4.7.5.01 build21752\r\n" +
"Cache-Control: no-cache\r\n" +
"Public: DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE, OPTIONS, ANNOUNCE, RECORD, GET_PARAMETER\r\n" +
"Supported: play.basic, con.persistent\r\n\r\n";
recvMsg(respMsg);
} else {
String respMsg = "RTSP/1.0 401 UNKNOWN\r\n" +
"CSeq: " + cseq + "\r\n" +
"Server: Wowza Streaming Engine 4.7.5.01 build21752\r\n" +
"Supported: play.basic, con.persistent\r\n\r\n";
recvMsg(respMsg);
}
continue;
}
if(sessionInfo.getUrl() != null) {
String redirectUrl = sessionInfo.getRedirectUrl();
if(!StringUtils.isEmpty(redirectUrl)) {
if(redirectUrl.endsWith("/")) redirectUrl = redirectUrl.substring(0,redirectUrl.length() - 1);
String url = sessionInfo.getUrl();
if(url.endsWith("/")) url = url.substring(0,url.length() - 1);
int idx;
while((idx = rtspMsg.indexOf(url)) > 0) {
rtspMsg = rtspMsg.substring(0,idx) + redirectUrl + rtspMsg.substring(idx + url.length());
}
}
/*
if("SETUP".equalsIgnoreCase(opName)) {
int div = lines.get(0).toLowerCase().indexOf("trackID=".toLowerCase());
if(div > 0) {
String trackID = lines.get(0).substring(div + "trackID=".length()).split(" ")[0];
}
}
*/
}
try {
System.out.println("[Send To Remote]===========================================================\r\n" + rtspMsg);
socket.getOutputStream().write(rtspMsg.getBytes());
} catch (Exception e) {
EventItem newEventItem = new EventItem();
newEventItem.eventType = EventItem.EVT_STOP_ALL;
queueEvent.put(newEventItem);
break;
}
} else {
String respMsg = "RTSP/1.0 401 UNKNOWN\r\n" +
"CSeq: " + cseq + "\r\n" +
"Server: Wowza Streaming Engine 4.7.5.01 build21752\r\n" +
"Supported: play.basic, con.persistent\r\n\r\n";
recvMsg(respMsg);
}
}
}
break;
case EventItem.EVT_STOP:
{
try {
eventItem.socket.close();
} catch(Exception e) {
}
if(eventItem.socket == socket) {
EventItem newEventItem = new EventItem();
newEventItem.eventType = EventItem.EVT_STOP_ALL;
queueEvent.put(newEventItem);
return;
} else {
}
}
break;
case EventItem.EVT_STOP_ALL:
{
if (socket != null) {
try {
socket.close();
} catch (Exception e) {
}
socket = null;
}
sessionInfo.close();
return;
}
}
}
} catch(Exception e) {
} finally {
System.out.println("RemoteExecThread Is Down!");
}
}
}
}
package com.yeejoin.amos.rtsp;
import java.util.HashMap;
public class SessionInfo {
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getRedirectUrl() {
return redirectUrl;
}
public void setRedirectUrl(String redirectUrl) {
this.redirectUrl = redirectUrl;
}
public LocalRtspService getLocalRtspService() {
return localRtspService;
}
public void setLocalRtspService(LocalRtspService localRtspService) {
this.localRtspService = localRtspService;
}
public RemoteRtspService getRemoteRtspService() {
return remoteRtspService;
}
public void setRemoteRtspService(RemoteRtspService remoteRtspService) {
this.remoteRtspService = remoteRtspService;
}
public void close() {
if(localRtspService != null) localRtspService.close();
if(remoteRtspService != null) remoteRtspService.close();
hsmpChannel2SessionInfo.remove(channel);
}
public String getChannel() {
return channel;
}
public SessionInfo() {
channel = Integer.toString(channelSeq ++);
synchronized (hsmpChannel2SessionInfo) {
hsmpChannel2SessionInfo.put(channel, this);
}
}
private LocalRtspService localRtspService = null;
private RemoteRtspService remoteRtspService = null;
private String redirectUrl = null;
private String url = null;
private String host = null;
private int port = 0;
private String channel = null;
private final static HashMap<String,SessionInfo> hsmpSessionInfo = new HashMap<String,SessionInfo>();
private final static HashMap<String,SessionInfo> hsmpChannel2SessionInfo = new HashMap<String,SessionInfo>();
private static int channelSeq = 0;
public static SessionInfo getByChannel(String channel) {
synchronized (hsmpChannel2SessionInfo) {
return hsmpChannel2SessionInfo.get(channel);
}
}
public static void add(String sessionId,SessionInfo sessionInfo) {
hsmpSessionInfo.put(sessionId,sessionInfo);
}
public static void remove(String sessionId) {
hsmpSessionInfo.remove(sessionId);
}
public static SessionInfo get(String sessionId) {
return hsmpSessionInfo.get(sessionId);
}
}
package com.yeejoin.amos.rtsp;
import org.springframework.util.StringUtils;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class Utils {
public static List<String> msg2lines(String s) {
BufferedReader br = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(s.getBytes(Charset.forName("utf8"))), Charset.forName("utf8")));
String line;
List<String> listLine = new ArrayList<String>();
try {
while ((line = br.readLine()) != null) {
listLine.add(line);
}
br.close();
} catch(Exception e) {
e.printStackTrace();
}
return listLine;
}
public static HashMap<String,String> list2key(List<String> lines, String div) {
return list2key(lines,div, 0);
}
public static HashMap<String,String> list2key(List<String> lines, String div, int parseLineIdx) {
HashMap<String,String> hsmpVal = new HashMap<String,String>();
for(int i=parseLineIdx;i<lines.size();i++) {
String line = lines.get(i).trim();
if(line.length() == 0)
continue;
int divIdx = line.indexOf(div);
if(divIdx <= 0)
continue;
String k = line.toLowerCase().substring(0,divIdx).trim();
String v = line.substring(divIdx + div.length()).trim();
hsmpVal.put(k,v);
}
return hsmpVal;
}
public static HashMap<String,String> parseUrl(String url) {
HashMap<String,String> hsmpVal = new HashMap<String,String>();
String protocol = url.split("://")[0];
if(!StringUtils.isEmpty(protocol)) {
String hostfull = url.split("://")[1].split("/")[0];
hostfull = (hostfull.indexOf('@') > 0) ? hostfull.split("@")[1] : hostfull;
String host = (hostfull.indexOf(':') >= 0) ? hostfull.split(":")[0] : hostfull;
int port = (hostfull.indexOf(':') >= 0) ? Integer.parseInt(hostfull.split(":")[1]) : 554;
String path = url.split("://")[1].split("^([^/]+)")[1];
hsmpVal.put("url",url);
hsmpVal.put("protocol",protocol);
hsmpVal.put("host",host);
hsmpVal.put("port",Integer.toString(port));
hsmpVal.put("path",path);
return hsmpVal;
} else {
return null;
}
}
}
package com.yeejoin.amos.rtsp;
public class WebSocketConfig {
public final static String PROXY_PROTOCOL = "WSP";
public final static String PROXY_VERSION = "1.1";
public final static String CMD_INIT = "INIT";
public final static String CMD_JOIN = "JOIN";
public final static String CMD_WRAP = "WRAP";
}
package com.yeejoin.amos.rtsp;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.util.StringUtils;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.HandshakeInterceptor;
import javax.servlet.http.HttpSession;
import java.util.Map;
public class WebSocketHandshakeInterceptor implements HandshakeInterceptor {
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
if (request instanceof ServletServerHttpRequest) {
ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
ServletServerHttpResponse servletResponse = (ServletServerHttpResponse) response;
String protocol = request.getHeaders().getFirst("Sec-WebSocket-Protocol");
if(!StringUtils.isEmpty(protocol))
response.getHeaders().set("Sec-WebSocket-Protocol",protocol);
HttpSession session = servletRequest.getServletRequest().getSession(false);
if (session != null) {
//session.setAttribute(Constants.Content);
//session.setAttribute(Constants.Encod);
//String userName = (String) session.getAttribute(Constants.SESSION_USERNAME);
//attributes.put(Constants.WEBSOCKET_USERNAME,userName);
}
}
return true;
}
@Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {
}
}
package com.yeejoin.amos.server;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Configuration //配置类注解,被自动扫描发现
@PropertySource("classpath:video/params.properties") //指明配置源文件位置
@ConfigurationProperties("param") //指明前缀
public class ParamsConfig {
/** 后台h5s服务 url */
private String remoteurl;
public String getRemoteurl() {
return remoteurl;
}
public void setRemoteurl(String remoteurl) {
this.remoteurl = remoteurl;
}
}
package com.yeejoin.amos.server;
import java.nio.charset.StandardCharsets;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import org.jboss.logging.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import com.yeejoin.amos.entity.DeviceBean;
import com.yeejoin.amos.entity.H5Response;
import com.yeejoin.amos.entity.Video;
@Service("remoteServer")
public class RemoteServer {
private static final Logger logger = Logger.getLogger(RemoteServer.class);
private String address;
@Resource(name = "paramsConfig")
private ParamsConfig paramsConfig;
private final RestTemplate restTemplate;
@Autowired
protected HttpServletRequest request;
public RemoteServer() {
this.restTemplate = new RestTemplate();
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public H5Response addDevice(Video bean) {
//String url = paramsConfig.getRemoteurl();
StringBuilder sb = new StringBuilder();
sb.append(paramsConfig.getRemoteurl()).append("/api/v1/AddSrcRTSP?name=").append(bean.getName())
.append('&').append("user=").append(bean.getUser())
.append('&').append("password=").append(bean.getPassword())
.append('&').append("token=").append(bean.getToken())
.append('&').append("playback=").append(false)
.append('&').append("audio=").append(true)
.append('&').append("session=").append("c1782caf-b670-42d8-ba90-2244d0b0ee83")
.append('&').append("url=").append(bean.getRtspAddress());
HttpHeaders headers = new HttpHeaders();
MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
headers.setContentType(type);
headers.add("Accept", MediaType.APPLICATION_JSON.toString());
headers.add("X-From-Service", "true");
restTemplate.getMessageConverters().set(1,new StringHttpMessageConverter(StandardCharsets.UTF_8));
ResponseEntity<H5Response> responseEntity = restTemplate.getForEntity(sb.toString(), H5Response.class,headers);
return responseEntity.getBody();
}
public DeviceBean getDevice(String token) {
StringBuilder sb = new StringBuilder();
sb.append(paramsConfig.getRemoteurl()).append("/api/v1/GetSrc?token=").append(token).append('&').append("session=").append("c1782caf-b670-42d8-ba90-2244d0b0ee83");
HttpHeaders headers = new HttpHeaders();
MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
headers.setContentType(type);
headers.add("Accept", MediaType.APPLICATION_JSON.toString());
headers.add("X-From-Service", "true");
restTemplate.getMessageConverters().set(1,new StringHttpMessageConverter(StandardCharsets.UTF_8));
ResponseEntity<DeviceBean> responseEntity = restTemplate.getForEntity(sb.toString(), DeviceBean.class,headers);
return responseEntity.getBody();
}
public H5Response deleteDevice(String token) {
StringBuilder sb = new StringBuilder();
sb.append(paramsConfig.getRemoteurl()).append("/api/v1/DelSrc?token=").append(token).append('&').append("session=").append("c1782caf-b670-42d8-ba90-2244d0b0ee83");
HttpHeaders headers = new HttpHeaders();
MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
headers.setContentType(type);
headers.add("Accept", MediaType.APPLICATION_JSON.toString());
headers.add("X-From-Service", "true");
restTemplate.getMessageConverters().set(1,new StringHttpMessageConverter(StandardCharsets.UTF_8));
ResponseEntity<H5Response> responseEntity = restTemplate.getForEntity(sb.toString(), H5Response.class,headers);
return responseEntity.getBody();
}
}
\ No newline at end of file
package com.yeejoin.amos.service;
public interface LoginService {
String login();
String applyToken();
String getToken();
}
package com.yeejoin.amos.service;
import com.github.pagehelper.PageHelper;
import com.yeejoin.amos.entity.BaseParam;
import com.yeejoin.amos.entity.PageModel;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
/**
* @Author: xinglei
* @Description: TODO()
* @Date: 2019/11/29 14:30
*/
@Service
public class PageService {
@Autowired
public SqlSessionTemplate sqlSession;
private String sqlId;
private String oraderByField;
private String oraderByType;
public PageService() {
}
public void setOraderByField(String oraderByField) {
this.oraderByField = oraderByField;
}
public void setOraderByType(String oraderByType) {
this.oraderByType = oraderByType;
}
public void setSqlId(String sqlId) {
this.sqlId = sqlId;
}
public List<Map<String, Object>> doService(BaseParam param) {
PageModel pageModel = new PageModel();
if (oraderByField == null || oraderByField.toString().trim().equals("") || oraderByType == null || !oraderByType.toString().equalsIgnoreCase("desc") && !oraderByType.toString().equalsIgnoreCase("asc")) {
if (this.oraderByField == null || this.oraderByField.trim().equals("") || this.oraderByType == null || !this.oraderByType.equalsIgnoreCase("desc") && !this.oraderByType.equalsIgnoreCase("asc")) {
PageHelper.startPage(param.getCurrent(), param.getPageSize());
} else {
PageHelper.startPage(param.getCurrent(), param.getPageSize(), Boolean.parseBoolean(this.oraderByField + " " + this.oraderByType));
}
} else {
PageHelper.startPage(param.getCurrent(), param.getPageSize(), Boolean.parseBoolean(oraderByField + " " + oraderByType));
}
List<Map<String, Object>> list = this.sqlSession.selectList(this.sqlId, param);
return list;
}
}
package com.yeejoin.amos.service;
import java.util.List;
import java.util.Map;
import com.alibaba.fastjson.JSONObject;
import com.yeejoin.amos.entity.DeviceBean;
import com.yeejoin.amos.entity.H5Response;
import com.yeejoin.amos.entity.MonitorParam;
import com.yeejoin.amos.entity.PageModel;
import com.yeejoin.amos.entity.Video;
public interface VideoService {
public PageModel<Video> findPageList(MonitorParam param);
List<Video> findAll(String floor3d);
List<Map<String, Object>> videoTree();
/**
* 添加设备
* @return
*/
H5Response addDevice(Video bean);
/**
* 删除设备
* @return
*/
H5Response deleteDevice(String token);
/**
* 查询设备信息
* @return
*/
Video getDevice(String token);
/**
* 更新设备
* @param bean
*/
public void updateDevice(Video bean);
}
package com.yeejoin.amos.service;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yeejoin.amos.dao.IVideoDao;
import com.yeejoin.amos.util.TreeDto;
import com.yeejoin.amos.util.TreeUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.yeejoin.amos.entity.H5Response;
import com.yeejoin.amos.entity.MonitorParam;
import com.yeejoin.amos.entity.PageModel;
import com.yeejoin.amos.entity.Video;
import com.yeejoin.amos.mapper.VideoMapper;
import com.yeejoin.amos.server.RemoteServer;
import org.springframework.util.ObjectUtils;
@Transactional
@Service
public class VideoServiceImpl implements VideoService {
@Autowired
VideoMapper mapper;
@Autowired
RemoteServer server;
@Autowired
IVideoDao videoDao;
@Override
public PageModel<Video> findPageList(MonitorParam param) {
List<Video> findPageList = mapper.findPageList(param.getStartPage(), param.getPageSize(), param.getName(),
param.getParentId());
Integer count = mapper.getCount(param.getName(), param.getParentId());
PageModel<Video> pm = new PageModel<>(count, param.getCurrent(), param.getPageSize(), findPageList);
return pm;
}
@Override
public List<Video> findAll(String floor3d) {
List<Video> findAll = mapper.findAll(floor3d);
return findAll;
}
@Override
public List<Map<String, Object>> videoTree() {
List<Map<String, Object>> resultList = new ArrayList<>();
List<Video> videos = videoDao.findAll();
List<TreeDto> rootNode = getRootNode();
List<TreeDto> treeDtos = buildNodeTree(rootNode, videos);
resultList = (List<Map<String, Object>>)(JSON.toJSON(treeDtos));
List<Map<String, Object>> list = new ArrayList<>();
resultList.forEach(
result -> {
Object children = result.get("children");
if (!ObjectUtils.isEmpty(children)) {
list.add(result);
}
}
);
return resultList;
}
@Override
public H5Response addDevice(Video bean) {
H5Response addDevice = server.addDevice(bean);
mapper.insertVideo(bean);
return addDevice;
}
@Override
public H5Response deleteDevice(String token) {
H5Response addDevice = server.deleteDevice(token);
mapper.deleteVideo(token);
return addDevice;
}
@Override
public Video getDevice(String token) {
Video selectByToken = mapper.selectByToken(token);
return selectByToken;
}
@Override
public void updateDevice(Video bean) {
mapper.updateVideo(bean);
}
private List<TreeDto> buildNodeTree(List<TreeDto> rootNode, List<Video> videos) {
List<TreeDto> list = new ArrayList<>();
videos.forEach(video -> {
TreeDto node = new TreeDto();
node.setId(video.getId().toString());
node.setIsLeaf(video.getIsLeaf().toString());
node.setName(video.getName());
node.setParentId(ObjectUtils.isEmpty(video.getParentId()) ? "" : video.getParentId().toString());
node.setUrl(video.getUrl());
node.setToken(video.getToken());
node.setUser(video.getUser());
node.setPassword(video.getPassword());
list.add(node);
});
return TreeUtil.findTree(rootNode, list);
}
private List<TreeDto> getRootNode() {
Map<String, Object> map = new HashMap<>();
List<Video> videos = mapper.selectByParentId();
ArrayList<TreeDto> rootNode = new ArrayList<>();
videos.forEach(
video -> {
TreeDto treeDto = new TreeDto();
treeDto.setName(video.getName());
treeDto.setId(video.getId().toString());
treeDto.setIsLeaf(video.getIsLeaf().toString());
treeDto.setParentId(ObjectUtils.isEmpty(video.getParentId()) ? "" : video.getParentId().toString());
treeDto.setUrl(video.getUrl());
treeDto.setToken(video.getToken());
treeDto.setUser(video.getUser());
treeDto.setPassword(video.getPassword());
rootNode.add(treeDto);
}
);
return rootNode;
}
}
package com.yeejoin.amos.util;
import com.yeejoin.amos.response.CommonResponse;
public class CommonResponseUtil
{
public static CommonResponse success() {
final CommonResponse response = new CommonResponse();
response.setResult("SUCCESS");
return response;
}
public static CommonResponse success(final Object obj) {
final CommonResponse response = new CommonResponse();
response.setResult("SUCCESS");
response.setDataList(obj);
return response;
}
public static CommonResponse success(final Object obj, final String message) {
final CommonResponse response = new CommonResponse();
response.setResult("SUCCESS");
response.setDataList(obj);
response.setMessage(message);
return response;
}
public static CommonResponse failure() {
final CommonResponse response = new CommonResponse();
response.setResult("FAILURE");
return response;
}
public static CommonResponse failure(final String message) {
final CommonResponse response = new CommonResponse();
response.setResult("FAILURE");
response.setMessage(message);
return response;
}
public static CommonResponse failure(final Object obj, final String message) {
final CommonResponse response = new CommonResponse();
response.setResult("FAILURE");
response.setDataList(obj);
response.setMessage(message);
return response;
}
}
package com.yeejoin.amos.util;
import lombok.Data;
import java.util.List;
/**
* @Author: xinglei
* @Description: TODO()
* @Date: 2019/12/2 13:58
*/
@Data
public class TreeDto {
private String id;
private String parentId;
private String name;
private String isLeaf;
private String url;
private String token;
private String user;
private String password;
private List<TreeDto> children;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getParentId() {
return parentId;
}
public void setParentId(String parentId) {
this.parentId = parentId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getIsLeaf() {
return isLeaf;
}
public void setIsLeaf(String isLeaf) {
this.isLeaf = isLeaf;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public List<TreeDto> getChildren() {
return children;
}
public void setChildren(List<TreeDto> children) {
this.children = children;
}
}
package com.yeejoin.amos.util;
import java.util.ArrayList;
import java.util.List;
/**
* @Author: xinglei
* @Description: TODO(树结构)
* @Date: 2019/12/2 13:57
*/
public class TreeUtil {
public static List<TreeDto> findTree(List<TreeDto> rootNode, List<TreeDto> mapList) {
rootNode.forEach(x -> {
List<TreeDto> childList = getChildNode(x.getId(), mapList);
x.setChildren(childList);
});
return rootNode;
}
public static List<TreeDto> getChildNode(String id, List<TreeDto> allNode) {
List<TreeDto> childList = new ArrayList<>();
allNode.forEach(x -> {
if (x.getParentId().equals(id)) {
childList.add(x);
}
});
childList.forEach(
x -> {
List<TreeDto> childNode = getChildNode(x.getId(), allNode);
x.setChildren(childNode);
if (childNode.size() > 0) {
x.setIsLeaf("1");
} else {
x.setIsLeaf("0");
}
}
);
childList.forEach(x -> x.setChildren(getChildNode(x.getId(), allNode)));
if (childList.size() == 0) {
return new ArrayList<>(0);
}
return childList;
}
}
1.项目说明:主要用于通过java执行ffmpeg命令的方式,向前端推流,实现视频直播
2.camera.json文件说明:
appName:摄像头应用的名称,跟在前端ws地址的最后面,如你的应用名是live1,则前端对于的hmtl文件中的ws地址是:ws://127.0.0.1:8082/live1
input:摄像机的rtsp地址,获取的方法是调用获取rtsp地址的接口/rtsp/address POST
ouput:这地址暂时固定的不要改,端口好如果冲突的话,要改端口的话对应的前端websocket.js中的端口好改成一样的就行,8081这个指的是ffpeng推送端口
3.rtsp地址获取接口
请求地址:POST http://localhost:9007/rtsp/address
请求体实例:
[
{
"port":"554", //端口固定的,不用改
"videoFormat":"h264", //固定的,不用改
"ip":"172.16.18.21", //摄像机Ip
"channel":"ch1", //固定的,不用改
"pwd":"zjt123456", //摄像机密码
"userName":"admin" //摄像机用户名
},
{
"port":"554",
"videoFormat":"h264",
"ip":"172.16.18.21",
"channel":"ch1",
"pwd":"zjt123456",
"userName":"admin"
}
]
响应:
{
"result": "SUCCESS",
"dataList": [
"rtsp://admin:zjt123456@172.16.18.21:554/h264/ch1/main/av_stream",
"rtsp://admin:zjt123456@172.16.18.21:554/h264/ch1/main/av_stream"
],
"message": null,
"success": true
4.项目启动后就已经启动配置的地址的推流
}
\ No newline at end of file
spring.application.name=amos_bank
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://47.103.14.66:3306/amos_xian_bank?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false&noAccessToProcedureBodies=true
spring.datasource.username = root
spring.datasource.password = root_123
# Keep the connection alive if idle for a long time (needed in production)
spring.datasource.testWhileIdle = true
spring.datasource.validationQuery = SELECT 1
#JPA Configuration:
# Show or not log for each sql query
spring.jpa.show-sql = true
# Hibernate ddl auto (create, create-drop, update): with "update" the database
# schema will be automatically updated accordingly to java entities found in
# the project
spring.jpa.hibernate.ddl-auto = none
# Naming strategy
#spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy
#spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
# Allows Hibernate to generate SQL optimized for a particular DBMS
spring.jpa.database-platform = org.hibernate.dialect.MySQLDialect
#mybatis
mybatis.mapper-locations=classpath:/db/mapper/*.xml
mybatis.type-aliases-package=com.yeejoin.amos.mapper
logging.level.com.yeejoin.amos.mapper=debug
#通用
server.port = 9007
#去除误报
logging.level.org.springframework.boot.autoconfigure: ERROR
[
{
"appName":"live1",
"input":"rtsp://admin:admin123@172.16.10.156:554/h264/ch1/main/av_stream",
"output":"http://127.0.0.1:8081/supersecret"
}
]
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd"
default-lazy-init="true">
<description>连接数据交互配置</description>
<!-- 数据源 -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${spring.datasource.driverClassName}" />
<property name="url" value="${spring.datasource.url}" />
<property name="username" value="${spring.datasource.username}" />
<property name="password" value="${spring.datasource.password}" />
</bean>
<!-- spring和MyBatis完美整合,不需要mybatis的配置映射文件 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="configuration" ref="mybatisConfigLocation"/>
<property name="dataSource" ref="dataSource" />
<!-- 自动扫描mapping.xml文件,**表示迭代查找 -->
<property name="mapperLocations" value="classpath*:db/mapper/*Mapper.xml" />
</bean>
<!-- mybatis spring sqlSessionTemplate,使用时直接让spring注入即可 -->
<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory"></constructor-arg>
</bean>
<!-- <bean id="baseDao" class="com.cicro.platform.dao.BaseDao">-->
<!-- <property name="sqlSession" ref="sqlSessionTemplate"/>-->
<!-- </bean>-->
<bean id="mybatisConfigLocation" class="org.apache.ibatis.session.Configuration">
<!--表示字段为空返回null-->
<property name="callSettersOnNulls" value="true"/>
</bean>
</beans>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd"
default-lazy-init="true">
<!-- 分页查询 -->
<bean id="queryMonitorVideoPageService" class="com.yeejoin.amos.service.PageService">
<property name="sqlId">
<value>getPageMonitorVideo</value>
</property>
</bean>
</beans>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yeejoin.amos.mapper.VideoMapper">
<sql id="pagelist">
id,
name,
is_leaf as isLeaf,
ip,
url as url,
rtsp_address as rtspAddress,
carmera_type as carmeraType,
parent_id as parentId,
text,
position3d,
floor3d,
is_indoor as isIndoor,
status as status,
token as token,
user,
password,
(@i:=@i+1) as i
</sql>
<sql id="videoField" >
id,
name,
is_leaf as isLeaf,
ip,
url as url,
rtsp_address as rtspAddress,
carmera_type as carmeraType,
parent_id as parentId,
text,
position3d,
floor3d,
is_indoor as isIndoor,
status as status,
token as token,
user,
password
</sql>
<select id="findAll" resultType="com.yeejoin.amos.entity.Video">
SELECT
id,name,parent_id as parentId,is_leaf as
isLeaf,ip,url,rtsp_address as rtspAddress,carmera_type as
carmeraType,text,
position3d,
floor3d,
is_indoor as isIndoor,
status as status,
token as token,
user,
password
FROM
b_monitor_video a
where 1=1
<if test="floor3d != null">
and a.floor3d=#{floor3d}
</if>
</select>
<select id="findPageList"
resultType="com.yeejoin.amos.entity.Video">
SELECT
<include refid="pagelist" />
FROM b_monitor_video a
,(select @i:=#{offset}) as it
where 1=1
<if test="name != null">
and a.name like concat('%',#{name},'%')
</if>
<if test="parentId != null">
and a.parent_id=#{parentId}
</if>
<if test="offset !=null and pageSize != null">
limit #{offset}, #{pageSize}
</if>
</select>
<select id="getCount" resultType="Integer">
SELECT COUNT(1) FROM b_monitor_video a
where 1=1
<if test="name != null">
and a.name like concat('%',#{name},'%')
</if>
<if test="parentId != null">
and a.parent_id=#{parentId}
</if>
</select>
<select id="getPageMonitorVideo" parameterType="java.util.Map" resultType="java.util.Map">
SELECT id, `name` FROM b_monitor_video
</select>
<delete id="deleteVideo" parameterType="java.lang.String">
delete from b_monitor_video where token = #{token}
</delete>
<select id="selectByToken"
resultType="com.yeejoin.amos.entity.Video">
SELECT
<include refid="videoField"/>
FROM b_monitor_video a
where 1=1
<if test="token != null">
and a.token like concat('%',#{token},'%')
</if>
</select>
<select id="selectByParentId"
resultType="com.yeejoin.amos.entity.Video">
SELECT
<include refid="videoField"/>
FROM b_monitor_video
where 1=1 and (parent_id IS NULL OR parent_id = '')
</select>
<insert id="insertVideo" parameterType="com.yeejoin.amos.entity.Video">
insert into b_monitor_video
(name,
parent_id,
ip,
rtsp_address,
url,
text,
carmera_type,
is_leaf,
position3d,
floor3d,
is_indoor,
status,
token,
user,
password)
values(
#{name},
#{parentId},
#{ip},
#{rtspAddress},
#{url},
#{text},
#{carmeraType},
#{isLeaf},
#{position3d},
#{floor3d},
#{isIndoor},
#{status},
#{token},
#{user},
#{password}
)
</insert>
<update id="updateVideo" parameterType="com.yeejoin.amos.entity.Video">
update b_monitor_video s
<set>
<if test="isLeaf!=null">
is_leaf=#{isLeaf},
</if>
<if test="url!=null">
url=#{url},
</if>
<if test="carmeraType!=null">
carmera_type=#{carmeraType},
</if>
<if test="parentId!=null">
parent_id=#{parentId},
</if>
<if test="text!=null">
text=#{text},
</if>
<if test="position3d!=null">
position3d=#{position3d},
</if>
<if test="floor3d!=null">
floor3d= #{floor3d},
</if>
<if test="isIndoor!=null">
is_indoor=#{isIndoor},
</if>
<if test="status!=null">
status=#{status}
</if>
</set>
where
s.id = #{id}
</update>
</mapper>
\ No newline at end of file
#ffmpeg执行路径,一般为ffmpeg的安装目录,该路径只能是目录,不能为具体文件路径,否则会报错
path=D:/soft/ffmpeg_124162/ffmpeg-20180605-b748772-win64-static/bin/
#存放任务的默认Map的初始化大小
size=10
#事件回调通知接口地址
callback=http://127.0.0.1/callback
#网络超时设置(毫秒)
timeout=300
#开启保活线程
keepalive=true
#是否输出debug消息
debug=true
<?xml version="1.0" encoding="UTF-8"?>
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
<id>package</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>true</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>bin</directory>
<outputDirectory>/</outputDirectory>
</fileSet>
<fileSet>
<directory>src/main/resources/config</directory>
<outputDirectory>/config/</outputDirectory>
</fileSet>
<fileSet>
<directory>src/main/resources/db</directory>
<outputDirectory>/db</outputDirectory>
</fileSet>
<fileSet>
<directory>src/main/resources/template</directory>
<outputDirectory>/template</outputDirectory>
</fileSet>
<fileSet>
<directory>src/main/resources</directory>
<includes>
<include>application.properties</include>
<include>apollo-env.properties</include>
<include>log4j.properties</include>
<include>META-INF/app.properties</include>
</includes>
<outputDirectory>/</outputDirectory>
</fileSet>
<fileSet>
<directory>${project.build.directory}</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>*.jar</include>
</includes>
</fileSet>
</fileSets>
<dependencySets>
<dependencySet>
<outputDirectory>lib</outputDirectory>
<scope>runtime</scope>
<!-- <unpack>false</unpack> -->
<excludes>
<!-- <exclude>${project.name}-${project.version}</exclude> -->
<exclude>${groupId}:${artifactId}</exclude>
</excludes>
</dependencySet>
</dependencySets>
</assembly>
\ No newline at end of file
[login]
login.lock.is_open=true
login.lock.login_times=5
login.lock.locked_time=10
[ocx]
playbackOcx.theme = Red
previewOcx.theme =Red
[platformSdk]
platformSdk.is_choose = false
[service-param]
net.protocol =http
\ No newline at end of file
param.remoteurl=http://localhost:8080
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment