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;
 
   48             Arrays.asList(
"mov", 
"m4v", 
"flv", 
"mp4", 
"3gp", 
"avi", 
"mpg", 
 
   49                     "mpeg", 
"asf", 
"divx", 
"rm", 
"moov", 
"wmv", 
"vob", 
"dat", 
 
   50                     "m1v", 
"m2v", 
"m4v", 
"mkv", 
"mpe", 
"yop", 
"vqa", 
"xmv", 
 
   51                     "mve", 
"wtv", 
"webm", 
"vivo", 
"vc1", 
"seq", 
"thp", 
"san", 
 
   52                     "mjpg", 
"smk", 
"vmd", 
"sol", 
"cpk", 
"sdp", 
"sbg", 
"rtsp", 
 
   53                     "rpl", 
"rl2", 
"r3d", 
"mlp", 
"mjpeg", 
"hevc", 
"h265", 
"265", 
 
   54                     "h264", 
"h263", 
"h261", 
"drc", 
"avs", 
"pva", 
"pmp", 
"ogg", 
 
   55                     "nut", 
"nuv", 
"nsv", 
"mxf", 
"mtv", 
"mvi", 
"mxg", 
"lxf", 
 
   56                     "lvf", 
"ivf", 
"mve", 
"cin", 
"hnm", 
"gxf", 
"fli", 
"flc", 
 
   57                     "flx", 
"ffm", 
"wve", 
"uv2", 
"dxa", 
"dv", 
"cdxl", 
"cdg", 
 
   58                     "bfi", 
"jv", 
"bik", 
"vid", 
"vb", 
"son", 
"avs", 
"paf", 
"mm", 
 
   62             Arrays.asList(
"application/x-shockwave-flash",
 
   79         return Collections.unmodifiableSortedSet(SUPPORTED_VIDEO_MIME_TYPES);
 
   98         return isMediaThumbnailSupported(file, 
"video/", SUPPORTED_VIDEO_MIME_TYPES, SUPPORTED_VIDEO_EXTENSIONS);
 
  101     @NbBundle.Messages({
"# {0} - file name",
 
  102         "VideoUtils.genVideoThumb.progress.text=extracting temporary file {0}"})
 
  103     static BufferedImage generateVideoThumbnail(AbstractFile file, 
int iconSize) {
 
  105         if (tempFile.exists() == 
false || tempFile.length() < file.getSize()) {
 
  106             ProgressHandle progress = ProgressHandle.createHandle(Bundle.VideoUtils_genVideoThumb_progress_text(file.getName()));
 
  109                 Files.createParentDirs(tempFile);
 
  110                 ContentUtils.writeToFile(file, tempFile, progress, null, 
true);
 
  111             } 
catch (IOException ex) {
 
  112                 LOGGER.log(Level.WARNING, 
"Error extracting temporary file for " + ImageUtils.getContentPathSafe(file), ex); 
 
  118         VideoCapture videoFile = 
new VideoCapture(); 
 
  120         if (!videoFile.open(tempFile.toString())) {
 
  121             LOGGER.log(Level.WARNING, 
"Error opening {0} for preview generation.", ImageUtils.getContentPathSafe(file)); 
 
  124         double fps = videoFile.get(CV_CAP_PROP_FPS); 
 
  125         double totalFrames = videoFile.get(CV_CAP_PROP_FRAME_COUNT); 
 
  126         if (fps <= 0 || totalFrames <= 0) {
 
  127             LOGGER.log(Level.WARNING, 
"Error getting fps or total frames for {0}", ImageUtils.getContentPathSafe(file)); 
 
  130         double milliseconds = 1000 * (totalFrames / fps); 
 
  132         double timestamp = Math.min(milliseconds, 500); 
 
  134         int framkeskip = Double.valueOf(Math.floor((milliseconds - timestamp) / (THUMB_COLUMNS * THUMB_ROWS))).intValue();
 
  136         Mat imageMatrix = 
new Mat();
 
  137         BufferedImage bufferedImage = null;
 
  141                 if (!videoFile.set(CV_CAP_PROP_POS_MSEC, timestamp + x * framkeskip + y * framkeskip * THUMB_COLUMNS)) {
 
  142                     LOGGER.log(Level.WARNING, 
"Error seeking to " + timestamp + 
"ms in {0}", ImageUtils.getContentPathSafe(file)); 
 
  146                 if (!videoFile.read(imageMatrix)) {
 
  147                     LOGGER.log(Level.WARNING, 
"Error reading frames at " + timestamp + 
"ms from {0}", ImageUtils.getContentPathSafe(file)); 
 
  151                 if (bufferedImage == null) {
 
  152                     bufferedImage = 
new BufferedImage(imageMatrix.cols() * 
THUMB_COLUMNS, imageMatrix.rows() * 
THUMB_ROWS, BufferedImage.TYPE_3BYTE_BGR);
 
  155                 byte[] data = 
new byte[imageMatrix.rows() * imageMatrix.cols() * (int) (imageMatrix.elemSize())];
 
  156                 imageMatrix.get(0, 0, data); 
 
  159                 if (imageMatrix.channels() == 3) {
 
  160                     for (
int k = 0; k < data.length; k += 3) {
 
  162                         data[k] = data[k + 2];
 
  167                 bufferedImage.getRaster().setDataElements(imageMatrix.cols() * x, imageMatrix.rows() * y, imageMatrix.cols(), imageMatrix.rows(), data);
 
  173         return bufferedImage == null ? null : ScalrWrapper.resizeFast(bufferedImage, iconSize);
 
static List< String > getSupportedVideoExtensions()
static final int CV_CAP_PROP_FRAME_COUNT
static final int THUMB_ROWS
String getTempDirectory()
static SortedSet< String > getSupportedVideoMimeTypes()
static final int THUMB_COLUMNS
static final List< String > SUPPORTED_VIDEO_EXTENSIONS
static final int CV_CAP_PROP_FPS
static final SortedSet< String > SUPPORTED_VIDEO_MIME_TYPES
static Case getCurrentCase()
synchronized static Logger getLogger(String name)
static final int CV_CAP_PROP_POS_MSEC
static File getTempVideoFile(AbstractFile file)
static boolean isVideoThumbnailSupported(AbstractFile file)