package com.shootoff.camera; import java.awt.Dimension; import java.awt.image.BufferedImage; import java.io.File; import java.util.Optional; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.shootoff.camera.cameratypes.Camera; import com.shootoff.camera.cameratypes.CameraEventListener; import com.shootoff.camera.shotdetection.JavaShotDetector; import com.shootoff.camera.shotdetection.ShotDetector; import com.xuggle.mediatool.IMediaListener; import com.xuggle.mediatool.IMediaReader; import com.xuggle.mediatool.MediaListenerAdapter; import com.xuggle.mediatool.ToolFactory; import com.xuggle.mediatool.event.ICloseEvent; import com.xuggle.mediatool.event.IVideoPictureEvent; public class MockCamera extends MediaListenerAdapter implements Camera { protected static final Logger logger = LoggerFactory.getLogger(MockCamera.class); protected File videoFile; protected long lastVideoTimestamp = -1; protected static final int SECOND_IN_MICROSECONDS = 1000 * 1000; protected Optional<CameraEventListener> cameraEventListener = Optional.empty(); public MockCamera() { super(); } public MockCamera(File videoFile) { super(); this.videoFile = videoFile; } @Override public boolean isOpen() { return true; } @Override public String getName() { return "MockCamera"; } public void run() { if (videoFile == null) return; IMediaReader reader = ToolFactory.makeReader(videoFile.getAbsolutePath()); reader.setBufferedImageTypeToGenerate(BufferedImage.TYPE_3BYTE_BGR); reader.addListener(this); logger.trace("opening {}", videoFile.getAbsolutePath()); while (reader.readPacket() == null) do {} while (false); } public void processVideo(IMediaListener listener) { IMediaReader reader = ToolFactory.makeReader(videoFile.getAbsolutePath()); reader.setBufferedImageTypeToGenerate(BufferedImage.TYPE_3BYTE_BGR); reader.addListener(listener); logger.trace("opening {}", videoFile.getAbsolutePath()); while (reader.readPacket() == null) do {} while (false); } private long initialSystemTimeAtVideoStart = -1; protected long currentFrameTimestamp = -1; private int frameCount = 0; public static final int DEFAULT_FPS = 30; private double webcamFPS = 0.0; @Override public void onVideoPicture(IVideoPictureEvent event) { BufferedImage currentFrame = event.getImage(); if (initialSystemTimeAtVideoStart == -1) initialSystemTimeAtVideoStart = System.currentTimeMillis(); currentFrameTimestamp = (event.getTimeStamp() / 1000) + initialSystemTimeAtVideoStart; if (frameCount == 0) { if (cameraEventListener.isPresent()) setViewSize(new Dimension(currentFrame.getWidth(), currentFrame.getHeight())); cameraEventListener.get().setFeedResolution(currentFrame.getWidth(), currentFrame.getHeight()); } if (lastVideoTimestamp > -1 && (frameCount % 30) == 0) { double estimateFPS = (double) SECOND_IN_MICROSECONDS / (double) (event.getTimeStamp() - lastVideoTimestamp); setFPS(estimateFPS); } lastVideoTimestamp = event.getTimeStamp(); if (cameraEventListener.isPresent()) cameraEventListener.get().newFrame(new Frame(Camera.bufferedImageToMat(currentFrame), currentFrameTimestamp)); frameCount++; } protected void setFPS(double newFPS) { // This just tells us if it's the first FPS estimate if (getFrameCount() > DEFAULT_FPS) webcamFPS = ((webcamFPS * 4.0) + newFPS) / 5.0; else webcamFPS = newFPS; } @Override public void onClose(ICloseEvent event) { if (cameraEventListener.isPresent()) cameraEventListener.get().cameraClosed(); } @Override public Frame getFrame() { return null; } @Override public BufferedImage getBufferedImage() { return null; } @Override public boolean open() { return false; } @Override public void close() { return; } @Override public void setCameraEventListener(CameraEventListener cameraEventListener) { this.cameraEventListener = Optional.of(cameraEventListener); } @Override public int getFrameCount() { return frameCount; } @Override public ShotDetector getPreferredShotDetector(CameraManager cameraManager, CameraView cameraView) { if (JavaShotDetector.isSystemSupported()) return new JavaShotDetector(cameraManager, cameraView); else return null; } @Override public boolean isLocked() { return false; } private Dimension size = null; @Override public void setViewSize(Dimension size) { this.size = size; } @Override public Dimension getViewSize() { return size; } @Override public double getFPS() { return webcamFPS; } @Override public boolean setState(CameraState state) { return true; } public CameraState getState() { return CameraState.DETECTING; } @Override public boolean supportsExposureAdjustment() { return false; } public boolean decreaseExposure() { return false; } public void resetExposure() { return; } @Override public boolean limitsFrames() { return false; } }