package com.yunzhi.inte.rtsp; import com.yunzhi.inte.InteApplication; import io.netty.channel.group.ChannelGroup; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import java.io.IOException; import java.util.*; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; /** * 转码 */ @Slf4j public class TransferRtspHelper { private static final ScheduledExecutorService SCHEDULE = Executors.newScheduledThreadPool(2); private static final ExecutorService PROCESS_EXECUTOR = Executors.newCachedThreadPool(); private static Map<String, Transfer> transferMap = new HashMap<>(); /** * 开启 */ public static synchronized void open(String ip) throws IOException { Transfer transfer = transferMap.get(ip); if (transfer == null) { transfer = new Transfer(); transfer.setIp(ip); transfer.setStartTime(new Date()); transfer.setContinueTime(new Date()); transfer.setCount(1); PROCESS_EXECUTOR.submit(new TransferTask(transfer)); transferMap.put(ip, transfer); } else { transfer.setContinueTime(new Date()); transfer.incCount(); } log.info("开始转码:{}", transfer); } /** * 关闭 */ public static synchronized void close(String ip) { Transfer transfer = transferMap.get(ip); if (transfer != null) { transfer.decCount(); if (transfer.getCount() <= 0) { Process process = transfer.getProcess(); if (process != null && process.isAlive()) { process.destroy(); } transferMap.remove(ip); } } log.info("结束转码:{}", transfer); } /** * 若当前有在转码,打印相关信息 */ public static void report() { Map<String, ChannelGroup> channelGroups = ChannelGroupHolder.getChannelGroups(); transferMap.forEach((k, v) -> { ChannelGroup group = channelGroups.get(k); if (group != null && !group.isEmpty()) { log.info("当前转码中:{}", v); } }); } /** * 如果没有对应channel,停止转码,如果前端页面还开着,会自动建立回连接 */ public static void clear() { List<String> toClearIp = new ArrayList<>(); Map<String, ChannelGroup> channelGroups = ChannelGroupHolder.getChannelGroups(); transferMap.forEach((k, v) -> { ChannelGroup group = channelGroups.get(k); if (group == null || group.isEmpty() || System.currentTimeMillis() - v.getContinueTime().getTime() > 1800_000L) { toClearIp.add(k); } }); if (!toClearIp.isEmpty()) { log.info("关闭以下无效转码:{}", toClearIp); toClearIp.forEach(TransferRtspHelper::close); } } /** * 开启定时器 */ public static void schedule() { SCHEDULE.scheduleAtFixedRate(TransferRtspHelper::report, 1L, 5L, TimeUnit.MINUTES); SCHEDULE.scheduleAtFixedRate(TransferRtspHelper::clear, 60L, 5L, TimeUnit.SECONDS); } @Data @NoArgsConstructor @AllArgsConstructor private static class Transfer { private String ip; private Process process; private int count; private Date startTime; private Date continueTime; public void incCount() { count++; } public void decCount() { count--; } } @Data @NoArgsConstructor @AllArgsConstructor public static class TransferTask implements Runnable { private Transfer transfer; public static FFmpeg fFmpeg; @SneakyThrows @Override public void run() { try { String ip = transfer.getIp(); Process process = fFmpeg.run(ip); transfer.setProcess(process); } catch (Exception e) { e.printStackTrace(); } } } }