19 package org.sleuthkit.autopsy.coreutils;
 
   21 import com.google.common.io.Files;
 
   22 import java.awt.image.BufferedImage;
 
   24 import java.io.IOException;
 
   25 import java.nio.file.Paths;
 
   26 import java.util.Arrays;
 
   27 import java.util.Collections;
 
   28 import java.util.List;
 
   29 import java.util.SortedSet;
 
   30 import java.util.TreeSet;
 
   31 import java.util.logging.Level;
 
   32 import org.netbeans.api.progress.ProgressHandle;
 
   33 import org.opencv.core.Mat;
 
   34 import org.opencv.highgui.VideoCapture;
 
   35 import org.openide.util.NbBundle;
 
   49             = Arrays.asList(
"mov", 
"m4v", 
"flv", 
"mp4", 
"3gp", 
"avi", 
"mpg", 
 
   50                     "mpeg", 
"asf", 
"divx", 
"rm", 
"moov", 
"wmv", 
"vob", 
"dat", 
 
   51                     "m1v", 
"m2v", 
"m4v", 
"mkv", 
"mpe", 
"yop", 
"vqa", 
"xmv", 
 
   52                     "mve", 
"wtv", 
"webm", 
"vivo", 
"vc1", 
"seq", 
"thp", 
"san", 
 
   53                     "mjpg", 
"smk", 
"vmd", 
"sol", 
"cpk", 
"sdp", 
"sbg", 
"rtsp", 
 
   54                     "rpl", 
"rl2", 
"r3d", 
"mlp", 
"mjpeg", 
"hevc", 
"h265", 
"265", 
 
   55                     "h264", 
"h263", 
"h261", 
"drc", 
"avs", 
"pva", 
"pmp", 
"ogg", 
 
   56                     "nut", 
"nuv", 
"nsv", 
"mxf", 
"mtv", 
"mvi", 
"mxg", 
"lxf", 
 
   57                     "lvf", 
"ivf", 
"mve", 
"cin", 
"hnm", 
"gxf", 
"fli", 
"flc", 
 
   58                     "flx", 
"ffm", 
"wve", 
"uv2", 
"dxa", 
"dv", 
"cdxl", 
"cdg", 
 
   59                     "bfi", 
"jv", 
"bik", 
"vid", 
"vb", 
"son", 
"avs", 
"paf", 
"mm", 
 
   63             Arrays.asList(
"application/x-shockwave-flash",
 
   80         return Collections.unmodifiableSortedSet(SUPPORTED_VIDEO_MIME_TYPES);
 
  122     @NbBundle.Messages({
"# {0} - file name",
 
  123         "VideoUtils.genVideoThumb.progress.text=extracting temporary file {0}"})
 
  124     static BufferedImage generateVideoThumbnail(AbstractFile file, 
int iconSize) {
 
  125         java.io.File tempFile;
 
  128         } 
catch (NoCurrentCaseException ex) {
 
  129             LOGGER.log(Level.WARNING, 
"Exception while getting open case.", ex); 
 
  132         if (tempFile.exists() == 
false || tempFile.length() < file.getSize()) {
 
  133             ProgressHandle progress = ProgressHandle.createHandle(Bundle.VideoUtils_genVideoThumb_progress_text(file.getName()));
 
  136                 Files.createParentDirs(tempFile);
 
  137                 if (Thread.interrupted()) {
 
  140                 ContentUtils.writeToFile(file, tempFile, progress, null, 
true);
 
  141             } 
catch (IOException ex) {
 
  142                 LOGGER.log(Level.WARNING, 
"Error extracting temporary file for " + ImageUtils.getContentPathSafe(file), ex); 
 
  147         VideoCapture videoFile = 
new VideoCapture(); 
 
  148         BufferedImage bufferedImage = null;
 
  151             if (!videoFile.open(tempFile.toString())) {
 
  152                 LOGGER.log(Level.WARNING, 
"Error opening {0} for preview generation.", ImageUtils.getContentPathSafe(file)); 
 
  155             double fps = videoFile.get(CV_CAP_PROP_FPS); 
 
  156             double totalFrames = videoFile.get(CV_CAP_PROP_FRAME_COUNT); 
 
  157             if (fps <= 0 || totalFrames <= 0) {
 
  158                 LOGGER.log(Level.WARNING, 
"Error getting fps or total frames for {0}", ImageUtils.getContentPathSafe(file)); 
 
  161             if (Thread.interrupted()) {
 
  165             double duration = 1000 * (totalFrames / fps); 
 
  178             int[] framePositions = 
new int[] {
 
  179                 (int) (duration * FRAME_GRAB_POS_RATIO[0]),
 
  180                 (int) (duration * FRAME_GRAB_POS_RATIO[1]),
 
  181                 (int) (duration * FRAME_GRAB_POS_RATIO[2]),
 
  182                 (int) (duration * FRAME_GRAB_POS_RATIO[3]),
 
  185             Mat imageMatrix = 
new Mat();
 
  187             for (
int i=0; i < framePositions.length; i++) {
 
  188                 if (!videoFile.set(CV_CAP_PROP_POS_MSEC, framePositions[i])) {
 
  189                     LOGGER.log(Level.WARNING, 
"Error seeking to " + framePositions[i] + 
"ms in {0}", ImageUtils.getContentPathSafe(file)); 
 
  194                 if (!videoFile.read(imageMatrix)) {
 
  195                     LOGGER.log(Level.WARNING, 
"Error reading frame at " + framePositions[i] + 
"ms from {0}", ImageUtils.getContentPathSafe(file)); 
 
  204             if (imageMatrix.empty()) {
 
  208             int matrixColumns = imageMatrix.cols();
 
  209             int matrixRows = imageMatrix.rows();
 
  212             if (bufferedImage == null) {
 
  213                 bufferedImage = 
new BufferedImage(matrixColumns, matrixRows, BufferedImage.TYPE_3BYTE_BGR);
 
  216             byte[] data = 
new byte[matrixRows * matrixColumns * (int) (imageMatrix.elemSize())];
 
  217             imageMatrix.get(0, 0, data); 
 
  220             if (imageMatrix.channels() == 3) {
 
  221                 for (
int k = 0; k < data.length; k += 3) {
 
  223                     data[k] = data[k + 2];
 
  228             bufferedImage.getRaster().setDataElements(0, 0, matrixColumns, matrixRows, data);
 
  232         if (Thread.interrupted()) {
 
  235         return bufferedImage == null ? null : ScalrWrapper.resizeFast(bufferedImage, iconSize);
 
  254             throw new IllegalStateException(ex);
 
static List< String > getSupportedVideoExtensions()
static final int CV_CAP_PROP_FRAME_COUNT
static File getVideoFileInTempDir(AbstractFile file)
String getTempDirectory()
static final double[] FRAME_GRAB_POS_RATIO
static SortedSet< String > getSupportedVideoMimeTypes()
static final List< String > SUPPORTED_VIDEO_EXTENSIONS
static final int CV_CAP_PROP_FPS
static final SortedSet< String > SUPPORTED_VIDEO_MIME_TYPES
synchronized static Logger getLogger(String name)
static Case getCurrentCaseThrows()
static final int CV_CAP_PROP_POS_MSEC
static File getTempVideoFile(AbstractFile file)
static boolean isVideoThumbnailSupported(AbstractFile file)