# demo **Repository Path**: itest-code/demo ## Basic Information - **Project Name**: demo - **Description**: No description available - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2019-05-08 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ```java package cn.com.here.service.impl; import cn.com.here.constant.HereConstant; import cn.com.here.domain.ImageInfo; import org.apache.commons.lang3.StringUtils; import org.bytedeco.javacpp.*; import org.bytedeco.javacv.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import java.io.File; import java.io.IOException; import java.util.Date; import java.util.LinkedList; import java.util.Queue; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import static org.bytedeco.javacpp.opencv_core.meanStdDev; import static org.bytedeco.javacpp.opencv_imgproc.*; import static org.bytedeco.javacpp.opencv_objdetect.CV_HAAR_DO_CANNY_PRUNING; import static org.opencv.core.CvType.CV_64F; public class MediaService implements Runnable{ private static final Logger logger = LoggerFactory.getLogger(MediaService.class); private static final ConcurrentHashMap MEDIA_SERVICE = new ConcurrentHashMap<>(); private static final ExecutorService cachedThreadPool = Executors.newCachedThreadPool(); private FFmpegFrameRecorderPlus recorder; // private FFmpegFrameGrabber grabber; private FrameGrabber grabber; private String rtspPath; private String out_file; public String rtmpPath; private Queue queue; private Integer cameraId; private boolean stop = false; private boolean pause = false; private int width = 1280; private int height = 600; private int audiocodecid; private int codecid; private double framerate; private int bitrate; private int audioChannels; private int audioBitrate; private int sampleRate; private opencv_objdetect.CascadeClassifier faceDetector; public MediaService(String rtmpPath,String rtspPath,Integer cameraId,String out_file,Queue queue) { this.rtspPath = rtspPath; this.cameraId = cameraId; this.rtmpPath = rtmpPath; this.out_file = out_file; this.queue = queue; // Resource resource = new ClassPathResource("haarcascade_frontalface_alt2.xml"); // if(resource != null){ // try { // this.faceDetector = new opencv_objdetect.CascadeClassifier(resource.getURI().getPath()); // } catch (IOException e) { // e.printStackTrace(); // } // } String path = System.getProperty("haar.path"); if(path == null){ logger.error("con not found haarcascade file, set jvm env by -Dhaar.path=filepath"); } this.faceDetector = new opencv_objdetect.CascadeClassifier(path); } public void initRecoder(String rtmpPath) throws FrameRecorder.Exception { recorder = new FFmpegFrameRecorderPlus(rtmpPath,width,height); recorder.setInterleaved(true); // recorder.setVideoOption("crf","28"); recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264); // 28 recorder.setFormat("flv"); // rtmp的类型 recorder.setFrameRate(framerate); recorder.setGopSize(20); recorder.setImageWidth(width); recorder.setImageHeight(height); recorder.setPixelFormat(0); // yuv420p recorder.setOption("nobuffer", "0"); recorder.setOption("fflags", "nobuffer"); recorder.setOption("tune","zerolatency"); recorder.setVideoOption("tune","zerolatency"); recorder.setVideoOption("preset","ultrafast"); recorder.setOption("preset","ultrafast"); logger.info("recorder start"); recorder.start(); } public boolean simpleFaceDetect(opencv_core.Mat image){ opencv_core.RectVector faces=new opencv_core.RectVector();//创建用来装检测出来的人脸的容器 opencv_core.Size minSize = new opencv_core.Size(10,10); opencv_core.Size maxSize = new opencv_core.Size(200,200); faceDetector.detectMultiScale(image,faces,1.1,3,CV_HAAR_DO_CANNY_PRUNING,minSize,maxSize); if(faces.size() != 0){ return true; } return false; } public void initGrabber() throws FrameGrabber.Exception { // grabber = FrameGrabber.createDefault(0); grabber = FFmpegFrameGrabber.createDefault(rtspPath); grabber.setOption("rtsp_transport", "tcp"); // 使用tcp的方式,不然会丢包很严重 // grabber.setOption("nobuffer", "0"); // grabber.setOption("fflags", "nobuffer"); // grabber.setFrameRate(50); //grabber.setImageWidth(width); //grabber.setImageHeight(height); logger.info("grabber start"); grabber.start(); // 采集/抓取器 // grabber = new FFmpegFrameGrabber(rtspPath); // grabber = FrameGrabber.createDefault(0); // if(rtspPath.indexOf("rtsp")>=0) { // grabber.setOption("rtsp_transport","tcp"); // } // grabber.start();// 开始之后ffmpeg会采集视频信息,之后就可以获取音视频信息 if(grabber.getImageWidth() > 0){ width = grabber.getImageWidth(); } if(grabber.getImageHeight() > 0){ height = grabber.getImageHeight(); } // // 视频参数 // audiocodecid = grabber.getAudioCodec(); // System.err.println("音频编码:" + audiocodecid); // codecid = grabber.getVideoCodec(); framerate = grabber.getFrameRate();// 帧率 // framerate = 25; // bitrate = grabber.getVideoBitrate();// 比特率 // // 音频参数 // // 想要录制音频,这三个参数必须有:audioChannels > 0 && audioBitrate > 0 && sampleRate > 0 // audioChannels = grabber.getAudioChannels(); // audioBitrate = grabber.getAudioBitrate(); // if (audioBitrate < 1) { // audioBitrate = 128 * 1000;// 默认音频比特率 // } } public static MediaService push(String rtspPath,Integer cameraId,String savePath,Queue queue) { String rtmpPath = HereConstant.RTMP_SERVER_ADDRESS + "/live/" + cameraId; if(MEDIA_SERVICE.containsKey(cameraId)){ return MEDIA_SERVICE.get(cameraId); } MediaService mediaService = new MediaService(rtmpPath,rtspPath,cameraId,savePath,queue); cachedThreadPool.execute(mediaService); MEDIA_SERVICE.put(cameraId,mediaService); return mediaService; } public static boolean stop(Integer cameraId){ if(MEDIA_SERVICE.containsKey(cameraId)){ MEDIA_SERVICE.get(cameraId).stopPush(); } return true; } public static void paush(Integer cameraId) { if(MEDIA_SERVICE.containsKey(cameraId)){ MEDIA_SERVICE.get(cameraId).pause(); } } public static void start(Integer cameraId){ if(MEDIA_SERVICE.containsKey(cameraId)){ MEDIA_SERVICE.get(cameraId).start(); } } private void pause() { this.pause = true; } public void start(){ this.pause = false; } private void stopPush() { this.stop = true; } public static void main(String[] args) throws Exception { //MediaService.recordCamera("rtmp://116.62.207.45:1953/hls/test",25); String rtmpPath = "rtmp://116.62.207.45:1953/live/30"; String rtspPath = "rtsp://admin:here123456@192.168.1.141:554/Streaming/Channels/101?transportmode=unicast"; String savePath = "/mnt/here/cache/30"; String path = MediaService.push(rtspPath,30,savePath,new LinkedList()).rtmpPath; System.out.println(path); while (true){} } @Override public void run() { try { initGrabber(); initRecoder(rtmpPath); logger.info("all start!!"); Frame rotatedFrame; long videoTS; long startTime = System.currentTimeMillis(); OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage(); // while((rotatedFrame=grabber.grabFrame()) != null){ int count = 0; while(!stop){ rotatedFrame=grabber.grabFrame(); if(rotatedFrame == null){ logger.info("frame image is null"); ++count; //重连 if(count >= 3){ grabber.stop(); grabber.release(); initGrabber(); count = 0; } } if (startTime == 0) { startTime = System.currentTimeMillis(); } videoTS = 1000 * (System.currentTimeMillis() - startTime); if(rotatedFrame!=null && rotatedFrame.imageHeight > 0 && rotatedFrame.imageWidth > 0){ // if(!pause && StringUtils.isNotBlank(out_file)){ // logger.info("start caculate image..............."); // long start = System.currentTimeMillis(); // final opencv_core.Mat mat = converter.convertToMat(rotatedFrame); // //new Thread(() -> { // //boolean hasFace = simpleFaceDetect(mat); // //if(hasFace){ // long seconds = new Date().getTime(); // String path = out_file + File.separator + seconds + ".jpg"; // opencv_imgcodecs.imwrite(path, mat); // if(queue != null){ // ImageInfo imageInfo = new ImageInfo(path,mat); // queue.offer(imageInfo); // } // //} // //}).start(); // logger.info("end caculate image ............ use {}ms",System.currentTimeMillis() - start); // } if(videoTS > recorder.getTimestamp()){ recorder.setTimestamp(videoTS); } recorder.record(rotatedFrame); } } grabber.stop(); logger.info("------------------camera connector is closed"); grabber.release(); recorder.stop(); recorder.release(); } catch (FrameGrabber.Exception | FrameRecorder.Exception e) { e.printStackTrace(); logger.error(e.getMessage(),e); } // try { // initGrabber(); // initRecoder(rtmpPath); // long err_index = 0;//采集或推流导致的错误次数 // //连续五次没有采集到帧则认为视频采集结束,程序错误次数超过1次即中断程序 // for(int no_frame_index=0;no_frame_index<5||err_index>1;) { // if(stop){ // break; // } // avcodec.AVPacket pkt=null; // try { // //没有解码的音视频帧 // pkt=grabber.grabPacket(); // if(pkt==null||pkt.size()<=0||pkt.data()==null) { // //空包记录次数跳过 // no_frame_index++; // continue; // } // //不需要编码直接把音视频帧推出去 // err_index+=(recorder.recordPacket(pkt)?0:1);//如果失败err_index自增1 // av_free_packet(pkt); // }catch (Exception e) {//推流失败 // err_index++; // logger.error(e.getMessage(),e); // } // } // } catch (FrameGrabber.Exception e) { // e.printStackTrace(); // logger.error(e.getMessage(),e); // } catch (FrameRecorder.Exception e) { // e.printStackTrace(); // logger.error(e.getMessage(),e); // } MEDIA_SERVICE.remove(cameraId); } public static double caculateQuality(opencv_core.Mat srcImage){ // opencv_core.Mat srcImage = opencv_imgcodecs.imread("/Users/cailuxiang/Desktop/obm.jpg"); opencv_core.Mat dstImage = new opencv_core.Mat(); cvtColor(srcImage, dstImage, COLOR_BGR2GRAY); //转化为灰度图 //在gray目录下生成灰度图片 // opencv_imgcodecs.imwrite("/Users/cailuxiang/Desktop/obm-grap.jpg", dstImage); opencv_core.Mat laplacianDstImage = new opencv_core.Mat(); //阈值太低会导致正常图片被误断为模糊图片,阈值太高会导致模糊图片被误判为正常图片 Laplacian(dstImage, laplacianDstImage, CV_64F); //在laplacian目录下升成经过拉普拉斯掩模做卷积运算的图片 // opencv_imgcodecs.imwrite("/Users/cailuxiang/Desktop/obm-ggg.jpg", laplacianDstImage); //矩阵标准差 opencv_core.Mat stddev = new opencv_core.Mat(); //求矩阵的均值与标准差 meanStdDev(laplacianDstImage, new opencv_core.Mat(), stddev); System.out.println("矩阵的标准差:\n" + stddev.createIndexer().getDouble()); return stddev.createIndexer().getDouble(); } } ```