IPC的集中调用方法(Java实现)

项目中涉及网络摄像头的相关内容,主要是视频流的解析送后端做各种处理,需要CS方式、BS方式等各种展现方式。

通常调用方法分为设备厂家SDK解析调用和RTSP协议读流解析调用两种大方法。

 

其中海康设备RTSP协议地址为:

rtsp://admin:[email protected]:554/h265/ch1/sub/av_stream

主要关心参数为sub、main(区分主辅流)

云视通RTSP地址:

rtsp://192.168.1.203:8554/live1.265

主要关心参数为live0、live1(区分主辅流)  264、265区分协议 根据设备自定

还可以用ONVIF协议去discover,这里就不累赘了。

 

本片主要介绍RTSP协议的集中调用方法:

1、javacv 方式调用RTSP格式视频流  适合低并发CS模式

http://mvnrepository.com/artifact/org.bytedeco.javacpp-presets/opencv/3.2.0-1.3

package cn.xsw.rtsp;

import java.awt.Image;
import java.io.IOException;

import javax.swing.ImageIcon;

import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.FrameGrabber;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.bytedeco.javacv.OpenCVFrameConverter;

import cn.xsw.tools.Config;
import cn.xsw.view.ATvMain;

/**
 * 通过rstp方式获取视频流的帧
 *
 * @author xswsoft 2018年3月22日15:40:54
 */
public class RtspUtils implements Runnable {

	static Java2DFrameConverter java2dFrameConverter = new Java2DFrameConverter();
	static OpenCVFrameConverter.ToIplImage converterImage = new OpenCVFrameConverter.ToIplImage();
	public static boolean startCap = false;
	static int frameDate = 1000000;
	private static FFmpegFrameGrabber grabber;

	public static void main(String[] args) throws InterruptedException, IOException {
	}

	public RtspUtils() {
		super();
		init();
		// TODO 自动生成的构造函数存根
	}

	private static void init() {
		String rstpAdd = Config.getPropertyByName("view_video_source");
		grabber = new FFmpegFrameGrabber(rstpAdd);
		// grabber.setOption("rtsp_transport", "tcp");
		// grabber.setImageHeight(704);
		// grabber.setImageWidth(576);
	}

	private static void capFrameImg(FFmpegFrameGrabber grabber) {
		try {
			if (startCap == false) {
				grabber.start();
				startCap = true;
			}
			Frame frame = null;
			while ((frame = grabber.grabFrame()) != null) {

				ImageIcon imgc2 = new ImageIcon(java2dFrameConverter.convert(frame));

				imgc2.setImage(imgc2.getImage().getScaledInstance(ATvMain.lbl_video.getWidth(),
						ATvMain.lbl_video.getHeight(), Image.SCALE_DEFAULT));

				ATvMain.lbl_video.setIcon(imgc2);
			}
		} catch (FrameGrabber.Exception e) {
			e.printStackTrace();
			System.out.println("抓图报错!");
		}
	}

	@Override
	public void run() {
		// TODO 自动生成的方法存根
		capFrameImg(grabber);
	}
}

抓到图后咋处理就看自己了。

需要的jar包如下图:

IPC的集中调用方法(Java实现)_第1张图片

优点:延迟低 <2s

2、webcam 方式   适合低并发CS模式

https://github.com/sarxos/webcam-capture

package cn.xsw.rtspview;

import java.awt.Dimension;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;

import javax.swing.JFrame;

import com.github.sarxos.webcam.Webcam;
import com.github.sarxos.webcam.WebcamPanel;
import com.github.sarxos.webcam.WebcamResolution;

import cn.xsw.utils.Config;
import uk.co.caprica.vlcj.medialist.MediaListItem;

public class WebcamRtspExample {

	static {
		String name = "Big Buck Bunny";
		String rtsp = Config.getPropertyByName("view_video_source");
		Webcam.setDriver(new VlcjDriver(Arrays.asList(new MediaListItem(name, rtsp, new ArrayList()))));
	}

	public static void main(String[] args) throws InterruptedException, IOException {

		// 自定义分辨率
		Dimension[] nonStandardResolutions = new Dimension[] {
				// 640 * 480
				WebcamResolution.VGA.getSize(),
				// 960 * 640
				WebcamResolution.DVGA.getSize(),
				// WXGA1 1366 * 768
				WebcamResolution.WXGA1.getSize(),
				// 自定义分辨率
				new Dimension(2000, 1000) };

		Dimension dimension = WebcamResolution.WXGA1.getSize();

		Webcam webcam = Webcam.getWebcams().get(0);

		webcam.setCustomViewSizes(nonStandardResolutions);
		webcam.setViewSize(dimension);

		WebcamPanel panel = new WebcamPanel(webcam);

		JFrame window = new JFrame("Webcam Panel");
		window.add(panel);
		window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		window.pack();
		window.setVisible(true);
	}
}
package cn.xsw.rtspview;

import java.awt.Dimension;
import java.awt.Transparency;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ComponentColorModel;
import java.awt.image.ComponentSampleModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.github.sarxos.webcam.WebcamDevice;
import com.github.sarxos.webcam.WebcamDevice.FPSSource;
import com.github.sarxos.webcam.WebcamException;
import com.github.sarxos.webcam.WebcamResolution;
import com.github.sarxos.webcam.util.OsUtils;
import com.sun.jna.Memory;

import uk.co.caprica.vlcj.medialist.MediaListItem;
import uk.co.caprica.vlcj.player.MediaPlayer;
import uk.co.caprica.vlcj.player.MediaPlayerFactory;
import uk.co.caprica.vlcj.player.direct.BufferFormat;
import uk.co.caprica.vlcj.player.direct.BufferFormatCallback;
import uk.co.caprica.vlcj.player.direct.DirectMediaPlayer;
import uk.co.caprica.vlcj.player.direct.RenderCallback;
import uk.co.caprica.vlcj.player.direct.format.RV32BufferFormat;


/**
 * This is capture driver which uses vlcj library to
 * access webcam hardware.
 *
 * @author Bartosz Firyn (SarXos)
 */
public class VlcjDevice implements WebcamDevice, BufferFormatCallback, RenderCallback, FPSSource {

	/**
	 * This class is to convert vlcj {@link Memory} to {@link BufferedImage}.
	 *
	 * @author Bartosz Firyn (sarxos)
	 */
	private static class Converter {

		/**
		 * Converters are cached and created on demand for every width-height tuple.
		 */
		private static final Map CONVERTERS = new HashMap();

		/**
		 * The buffer data type (buffer consist of 4 byte values for every pixel).
		 */
		final int dataType = DataBuffer.TYPE_BYTE;

		/**
		 * Number of bytes per pixel.
		 */
		final int pixelStride = 4;

		/**
		 * Number of bytes per line.
		 */
		final int scanlineStride;

		/**
		 * Band offsets for BGR components (B = 2, G = 1, R = 0).
		 */
		final int[] bgrBandOffsets = new int[] { 2, 1, 0 };

		/**
		 * Number of bits per component.
		 */
		final int[] bits = { 8, 8, 8 };

		/**
		 * Offset between pixels.
		 */
		final int[] offsets = new int[] { 0 };

		/**
		 * Transparency type (opaque since there is no transparency in the image).
		 */
		final int transparency = Transparency.OPAQUE;

		/**
		 * Color space, a standard default color space for the Internet - sRGB.
		 */
		final ColorSpace colorSpace = ColorSpace.getInstance(ColorSpace.CS_sRGB);

		/**
		 * Image sample model.
		 */
		final ComponentSampleModel sampleModel;

		/**
		 * Image color model.
		 */
		final ComponentColorModel colorModel = new ComponentColorModel(colorSpace, bits, false, false, transparency, dataType);

		private Converter(int width, int height) {
			this.scanlineStride = width * pixelStride;
			this.sampleModel = new ComponentSampleModel(dataType, width, height, pixelStride, scanlineStride, bgrBandOffsets);
		}

		/**
		 * Get memory converter for given width-height tuple.
		 *
		 * @param width the image width
		 * @param height the image height
		 * @return Converter
		 */
		public static Converter getConverter(int width, int height) {
			String key = key(width, height);
			Converter converter = CONVERTERS.get(key);
			if (converter == null) {
				converter = new Converter(width, height);
				CONVERTERS.put(key, converter);
			}
			return converter;
		}

		/**
		 * Use width and height to create map key.
		 *
		 * @param width the image width
		 * @param height the image height
		 * @return Map key
		 */
		private static String key(int width, int height) {
			return width + "x" + height;
		}

		/**
		 * Converts {@link Memory} into {@link BufferedImage}.
		 *
		 * @param buffers the {@link Memory} buffers
		 * @param format the image format
		 * @return {@link BufferedImage} created from {@link Memory}
		 */
		public BufferedImage convert(Memory[] buffers, BufferFormat format) {

			// sanity, check if buffers is not empty

			if (buffers.length == 0) {
				throw new RuntimeException("No memory elements found!");
			}

			// sanity check if buffer is not null

			final Memory memory = buffers[0];
			if (memory == null) {
				throw new RuntimeException("Null memory!");
			}

			// transfer bytes into array

			final byte[] bytes = new byte[scanlineStride * format.getHeight()];
			final byte[][] data = new byte[][] { bytes };

			memory
				.getByteBuffer(0, memory.size())
				.get(bytes);

			// create image

			DataBufferByte dataBuffer = new DataBufferByte(data, bytes.length, offsets);
			WritableRaster raster = Raster.createWritableRaster(sampleModel, dataBuffer, null);
			BufferedImage image = new BufferedImage(colorModel, raster, false, null);

			// flush reconstructable resources to free memory

			image.flush();

			// return image

			return image;
		}
	}

	/**
	 * Logger.
	 */
	private static final Logger LOG = LoggerFactory.getLogger(VlcjDevice.class);

	/**
	 * Artificial view sizes. The vlcj is not able to detect resolutions supported by the webcam. If
	 * you would like to detect resolutions and have high-quality with good performance images
	 * streaming, you should rather use gstreamer or v4lvj capture drivers.
	 */
	private final static Dimension[] RESOLUTIONS = new Dimension[] {
		WebcamResolution.QQVGA.getSize(),
		WebcamResolution.QVGA.getSize(),
		WebcamResolution.VGA.getSize(),
	};

	/**
	 * VLC args by Andrew Davison:
* http://fivedots.coe.psu.ac.th/~ad/jg/nui025/snapsWithoutJMF.pdf */ private final static String[] VLC_ARGS = { "--no-video-title-show", // do not display title "--no-stats", // no stats "--no-sub-autodetect-file", // no subtitles "--no-snapshot-preview", // no snapshot previews "--live-caching=50", // reduce capture lag/latency "--quiet", // turn off warnings }; /** * Used to calculate FPS. */ private long t1 = -1; /** * Used to calculate FPS. */ private long t2 = -1; /** * Image exchange reference. */ private final AtomicReference imageRef = new AtomicReference(); /** * Current FPS. */ private final AtomicReference fps = new AtomicReference((double) 0); private final MediaListItem item; private final MediaListItem sub; /** * Factory for media player instances. */ private MediaPlayerFactory factory; /** * Specification for a media player that provides direct access to the video frame data. */ private DirectMediaPlayer player; /** * Is in opening phase? */ private final AtomicBoolean opening = new AtomicBoolean(); /** * Is open? */ private final AtomicBoolean open = new AtomicBoolean(); /** * Is disposed? */ private final AtomicBoolean disposed = new AtomicBoolean(); /** * Current resolution. */ private Dimension resolution = null; protected VlcjDevice(MediaListItem item) { if (item == null) { throw new IllegalArgumentException("Media list item cannot be null!"); } this.item = item; this.sub = item.subItems().isEmpty() ? item : item.subItems().get(0); LOG.trace("New device created {}", this); } /** * Get capture device protocol. This will be: *
    *
  • dshow:// for Windows
  • *
  • qtcapture:// for Mac
  • *
  • v4l2:// for linux
  • *
* * @return Capture device protocol * @throws WebcamException in case when there is no support for given operating system */ public String getCaptureDevice() { switch (OsUtils.getOS()) { case WIN: return "dshow://"; case OSX: return "qtcapture://"; case NIX: return "v4l2://"; default: throw new WebcamException("Capture device not supported on " + OsUtils.getOS()); } } public MediaListItem getMediaListItem() { return item; } public MediaListItem getMediaListItemSub() { return sub; } @Override public String getName() { return sub.name(); } public String getMRL() { return sub.mrl(); } public String getVDevice() { return getMRL().replace(getCaptureDevice(), ""); } @Override public String toString() { return String.format("%s[%s (%s)]", getClass().getSimpleName(), getName(), getMRL()); } @Override public Dimension[] getResolutions() { return RESOLUTIONS; } @Override public Dimension getResolution() { return resolution; } @Override public void setResolution(Dimension resolution) { this.resolution = resolution; } @Override public BufferedImage getImage() { if (!open.get()) { throw new WebcamException("Cannot get image, webcam device is not open"); } BufferedImage image = null; // wait for image while ((image = imageRef.getAndSet(null)) == null) { try { Thread.sleep(10); } catch (InterruptedException e) { return null; } } return image; } @Override public synchronized void open() { if (disposed.get()) { LOG.warn("Cannot open device because it has been already disposed"); return; } if (open.get()) { return; } if (!opening.compareAndSet(false, true)) { return; } factory = new MediaPlayerFactory(VLC_ARGS); player = factory.newDirectMediaPlayer(this, this); LOG.info("Opening webcam device"); String[] options = null; switch (OsUtils.getOS()) { case WIN: LOG.debug("Open VLC device {}", getName()); options = new String[] { ":dshow-vdev=" + getName(), ":dshow-size=" + resolution.width + "x" + resolution.height, ":dshow-adev=none", // no audio device }; break; case NIX: LOG.debug("Open VLC device {}", getVDevice()); options = new String[] { ":v4l2-vdev=" + getVDevice(), ":v4l2-width=" + resolution.width, ":v4l2-height=" + resolution.height, ":v4l2-fps=30", ":v4l2-adev=none", // no audio device }; break; case OSX: LOG.debug("Open VLC device {}", getVDevice()); options = new String[] { ":qtcapture-vdev=" + getVDevice(), ":qtcapture-width=" + resolution.width, ":qtcapture-height=" + resolution.height, ":qtcapture-adev=none", // no audio device }; break; } player.startMedia(getMRL(), options); // wait for the first image long wait = 100; // ms int max = 100; int count = 0; while (imageRef.get() == null) { try { Thread.sleep(wait); } catch (InterruptedException e) { return; } if (count++ > max) { LOG.error("Unable to open in {} ms", wait * max); opening.set(false); return; } } open.set(true); opening.set(false); } @Override public synchronized void close() { LOG.info("Closing device {}", this); if (open.compareAndSet(true, false)) { player.stop(); } } @Override public synchronized void dispose() { if (!disposed.compareAndSet(false, true)) { return; } LOG.debug("Release resources (player={}, factory={})", player, factory); player.release(); factory.release(); } @Override public boolean isOpen() { return open.get(); } public MediaPlayer getPlayer() { return player; } @Override public BufferFormat getBufferFormat(int width, int height) { return new RV32BufferFormat(width, height); } @Override public void display(DirectMediaPlayer player, Memory[] buffers, BufferFormat format) { LOG.trace("Direct media player display invoked with format {}", format); // convert memory to image Converter converter = Converter.getConverter(format.getWidth(), format.getHeight()); BufferedImage image = converter.convert(buffers, format); imageRef.set(image); // calculate fps if (t1 == -1 || t2 == -1) { t1 = System.currentTimeMillis(); t2 = System.currentTimeMillis(); } t1 = t2; t2 = System.currentTimeMillis(); fps.set((4 * fps.get() + 1000 / (t2 - t1 + 1)) / 5); } @Override public double getFPS() { return fps.get(); } }
package cn.xsw.rtspview;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.github.sarxos.webcam.WebcamDevice;
import com.github.sarxos.webcam.WebcamDiscoverySupport;
import com.github.sarxos.webcam.WebcamDriver;
import com.github.sarxos.webcam.util.OsUtils;

import uk.co.caprica.vlcj.discovery.NativeDiscovery;
import uk.co.caprica.vlcj.medialist.MediaList;
import uk.co.caprica.vlcj.medialist.MediaListItem;
import uk.co.caprica.vlcj.player.MediaPlayerFactory;
import uk.co.caprica.vlcj.player.discoverer.MediaDiscoverer;


/**
 * This is capture driver which uses vlcj library to gain access to the camera device.
 * The library can be found at:
*
* http://www.capricasoftware.co.uk/projects/vlcj/index.html * * @author Bartosz Firyn (SarXos) */ public class VlcjDriver implements WebcamDriver, WebcamDiscoverySupport { /** * I'm the logger. */ private static final Logger LOG = LoggerFactory.getLogger(VlcjDriver.class); static { if ("true".equals(System.getProperty("webcam.debug"))) { System.setProperty("vlcj.log", "DEBUG"); } } /** * Are natives initialized. */ private static final AtomicBoolean initialized = new AtomicBoolean(); /** * Native library discoverer. */ private static NativeDiscovery nativeDiscovery; /** * The scan interval. */ private long scanInterval = -1; /** * Preconfigured media list items. */ private final List mediaListItems; public VlcjDriver() { this(null); } public VlcjDriver(List mediaListItems) { this.mediaListItems = mediaListItems; initialize(); } /** * Initialize natives. */ protected static void initialize() { initialize(true); } /** * Initialize natives. If argument is true the natives are being loaded. In case of false this * method do nothing. It's used mostly in unit tests. * * @param load the control to decide whether to load natives or ignore them */ protected static void initialize(boolean load) { if (load && initialized.compareAndSet(false, true)) { boolean nativeFound = getNativeDiscovery().discover(); if (!nativeFound) { throw new IllegalStateException("The libvlc native library has not been found"); } // Native.loadLibrary(RuntimeUtil.getLibVlcLibraryName(), LibVlc.class); } } @Override public List getDevices() { LOG.debug("Searching devices"); if (OsUtils.getOS() == OsUtils.WIN) { System.err.println("WARNING: VLCj does not support webcam devices discovery on Windows platform"); } List devices = new ArrayList(); if (mediaListItems != null) { for (MediaListItem item : mediaListItems) { devices.add(mediaListItemToDevice(item)); } } else { MediaPlayerFactory mediaPlayerFactory = createMediaPlayerFactory(); MediaDiscoverer videoMediaDiscoverer = mediaPlayerFactory.newVideoMediaDiscoverer(); MediaList videoDeviceList = videoMediaDiscoverer.getMediaList(); List videoDevices = videoDeviceList.items(); for (MediaListItem item : videoDevices) { LOG.debug("Found item {}", item); devices.add(mediaListItemToDevice(item)); } videoDeviceList.release(); videoMediaDiscoverer.release(); mediaPlayerFactory.release(); } return devices; } /** * Converts media list itemn into webcam device. * * @param item the item to be converted to webcam device instance * @return Webcam device created from media list item */ protected WebcamDevice mediaListItemToDevice(MediaListItem item) { return new VlcjDevice(item); } /** * Creates media player factory. * * @return New media player factory */ protected MediaPlayerFactory createMediaPlayerFactory() { return new MediaPlayerFactory(); } @Override public boolean isThreadSafe() { return false; } @Override public String toString() { return getClass().getSimpleName(); } @Override public long getScanInterval() { if (scanInterval <= 0) { return DEFAULT_SCAN_INTERVAL; } return scanInterval; } /** * Set new scan interval. Value must be positive number. If negative or zero is used, then the * corresponding getter will return default scan interval value. * * @param scanInterval the new scan interval in milliseconds * @see VlcjDriver#DEFAULT_SCAN_INTERVAL */ public void setScanInterval(long scanInterval) { this.scanInterval = scanInterval; } @Override public boolean isScanPossible() { return OsUtils.getOS() != OsUtils.WIN; } protected static NativeDiscovery getNativeDiscovery() { if (nativeDiscovery == null) { nativeDiscovery = new NativeDiscovery(); } return nativeDiscovery; } }

jar包:

IPC的集中调用方法(Java实现)_第2张图片

优点:简洁、跨平台好。 但延迟大3s左右

3、流媒体服务器接流转退RTMP、HLS等方式  适合BS   收费,便捷

https://www.linkingvision.com/

这个就看自己如何使用了,可以使用iframe嵌软件自带的页面,也可以自己写页面调用。

 

 

你可能感兴趣的:(java)