Java tutorial
/* * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. * * Copyright 2014, OpenSpace Solutions LLC. All Right Reserved. */ package com.chiorichan.dvr; import com.chiorichan.ChatColor; import com.chiorichan.Loader; import com.chiorichan.dvr.registry.VideoInput; import com.chiorichan.dvr.storage.Interface; import com.google.common.collect.Maps; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import static java.lang.Thread.sleep; import java.util.Map.Entry; import java.util.TreeMap; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; import javax.imageio.ImageIO; import net.lingala.zip4j.model.ZipParameters; import net.lingala.zip4j.util.Zip4jConstants; import org.joda.time.DateTime; /** * * @author Chiori Greene */ public class VideoWriter implements Runnable { public boolean isRunning; public Thread currentThread; private Interface storageInterface = new Interface(); private long lastTen = 0L; private ZipOutputStream containerStream = null; private boolean frameEncoding = false; private final TreeMap<DateTime, BufferedImage> timeCodedFrames = Maps.newTreeMap(); public boolean detachedFromInput = false; private final VideoInput vi; private File destFile; private ZipParameters parameters; public VideoWriter(VideoInput _vi) { vi = _vi; DVRLoader.getExecutor().execute(this); parameters = new ZipParameters(); parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE); parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL); parameters.setEncryptFiles(true); parameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_AES); parameters.setAesKeyStrength(Zip4jConstants.AES_STRENGTH_256); parameters.setPassword("OpenSpaceDVR2014"); // Generate a private key for each DVR install. Installation ID maybe? } @Override public void run() { currentThread = Thread.currentThread(); Loader.getLogger().info("Starting Video Writer Thread - " + currentThread.getName()); isRunning = true; do { try { if (containerStream == null) changeDestFile(); Entry<DateTime, BufferedImage> firstFrame = getFrame(); if (firstFrame != null) { frameHandler(firstFrame.getKey(), firstFrame.getValue()); timeCodedFrames.remove(firstFrame.getKey()); } Thread.sleep(10L); } catch (Exception ex) { Loader.getLogger().severe( "Exception Encountered in the Video Writer Thread (" + currentThread.getName() + ")", ex); } } while (DVRLoader.isRunning && !detachedFromInput); Loader.getLogger().info("Stopping Video Writer Thread - " + Thread.currentThread().getName()); try { finishUp(); } catch (IOException e) { e.printStackTrace(); } isRunning = false; currentThread = null; Loader.getLogger().info("Video Writer Thread STOPPED! - " + Thread.currentThread().getName()); } public synchronized void addFrame(DateTime dt, BufferedImage bi) { timeCodedFrames.put(dt, bi); } private synchronized Entry<DateTime, BufferedImage> getFrame() { if (timeCodedFrames.isEmpty()) return null; return timeCodedFrames.firstEntry(); } private void changeDestFile() throws IOException { File lastDestFile = destFile; destFile = storageInterface.calculateContainingFile(new DateTime(), vi.getChannelName()); Loader.getLogger().info( "New destination selected for input " + vi.getChannelName() + ": " + destFile.getAbsolutePath()); // Close previous zip stream if (containerStream != null) containerStream.finish(); // Open new zip stream containerStream = new ZipOutputStream(new FileOutputStream(destFile)); containerStream.setComment("OpenSpaceDVR video storage container!"); } private void frameHandler(DateTime dt, BufferedImage img) { try { if (img == null) return; frameEncoding = true; long start = System.currentTimeMillis(); if (lastTen != storageInterface.getTen(dt)) { lastTen = storageInterface.getTen(dt); changeDestFile(); } containerStream.putNextEntry(new ZipEntry(dt.getMillis() + ".jpg")); ByteArrayOutputStream bs = new ByteArrayOutputStream(); ImageIO.write(img, "JPG", bs); containerStream.write(bs.toByteArray()); containerStream.closeEntry(); Loader.getLogger() .info(ChatColor.YELLOW + "Writing Frame: Capture Time: " + dt.toString() + ", File Size: " + bs.size() + " bytes, Frames Buffered: " + timeCodedFrames.size() + ", Time Taken: " + (System.currentTimeMillis() - start) + ", Thread: " + Thread.currentThread().getName()); frameEncoding = false; } catch (IOException ex) { Loader.getLogger().severe("Exception encountered within the frameHandler method:", ex); } } private synchronized void finishUp() throws IOException { while (frameEncoding) { try { sleep(10); } catch (InterruptedException ex) { } } containerStream.close(); } }