From 0533655d80a20c9046378a5df058a2f921ec8ace Mon Sep 17 00:00:00 2001 From: Tim McIver Date: Tue, 2 Apr 2013 16:44:25 -0400 Subject: [PATCH 1/7] Removed dependency of MediaViewVideoPanel.captureFrames method on 'currentImage' member variable removing any concurrency issues involving that member variable. --- .../corecomponents/MediaViewVideoPanel.java | 47 ++++++++++--------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewVideoPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewVideoPanel.java index 1e0b890810..69a082719b 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewVideoPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewVideoPanel.java @@ -18,8 +18,8 @@ */ package org.sleuthkit.autopsy.corecomponents; -import java.awt.Color; import java.awt.Dimension; +import java.awt.Image; import java.awt.image.BufferedImage; import java.io.IOException; import java.nio.IntBuffer; @@ -47,11 +47,9 @@ import org.gstreamer.swing.VideoComponent; import org.netbeans.api.progress.ProgressHandle; import org.netbeans.api.progress.ProgressHandleFactory; import org.openide.util.Cancellable; -import org.openide.util.Exceptions; import org.openide.util.lookup.ServiceProvider; import org.openide.util.lookup.ServiceProviders; import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.datamodel.ContentUtils; @@ -69,8 +67,6 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt private static final Logger logger = Logger.getLogger(MediaViewVideoPanel.class.getName()); private boolean gstInited; - //frame capture - private BufferedImage currentImage = null; private static final long MIN_FRAME_INTERVAL_MILLIS = 500; //playback private long durationMillis = 0; @@ -284,23 +280,14 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt public List captureFrames(java.io.File file, int numFrames) { List frames = new ArrayList<>(); + FrameCaptureRGBListener rgbListener = new FrameCaptureRGBListener(); if (!isInited()) { return frames; } - RGBDataSink.Listener listener1 = new RGBDataSink.Listener() { - @Override - public void rgbFrame(boolean bln, int w, int h, IntBuffer rgbPixels) { - BufferedImage curImage = new BufferedImage(w, h, - BufferedImage.TYPE_INT_ARGB); - curImage.setRGB(0, 0, w, h, rgbPixels.array(), 0, w); - currentImage = curImage; - } - }; - // set up a PlayBin2 object - RGBDataSink videoSink = new RGBDataSink("rgb", listener1); + RGBDataSink videoSink = new RGBDataSink("rgb", rgbListener); PlayBin2 playbin = new PlayBin2("VideoFrameCapture"); playbin.setInputFile(file); playbin.setVideoSink(videoSink); @@ -317,7 +304,7 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt return frames; } - // create a list of timestamps at which to get frames + // calculate the number of frames to capture int numFramesToGet = numFrames; long frameInterval = myDurationMillis / numFrames; if (frameInterval < MIN_FRAME_INTERVAL_MILLIS) { @@ -331,23 +318,41 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt playbin.pause(); playbin.getState(); - currentImage = null; if (!playbin.seek(timeStamp, unit)) { logger.log(Level.INFO, "There was a problem seeking to " + timeStamp + " " + unit.name().toLowerCase()); } playbin.play(); - while (currentImage == null) { - System.out.flush(); // not sure why this is needed + Image image = null; + while (image == null) { + image = rgbListener.getImage(); } playbin.stop(); - frames.add(new VideoFrame(currentImage, timeStamp)); + frames.add(new VideoFrame(image, timeStamp)); } return frames; } + + private class FrameCaptureRGBListener implements RGBDataSink.Listener { + + private BufferedImage bi; + + @Override + public void rgbFrame(boolean bln, int w, int h, IntBuffer rgbPixels) { + bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); + bi.setRGB(0, 0, w, h, rgbPixels.array(), 0, w); + } + + public Image getImage() { + Image image = bi; + bi = null; + return image; + } + + } /** * This method is called from within the constructor to initialize the form. From ebbef618a5e035befd06d7d80941841c57d5aa11 Mon Sep 17 00:00:00 2001 From: Tim McIver Date: Tue, 2 Apr 2013 17:32:30 -0400 Subject: [PATCH 2/7] Added a line about tagging improvements to NEWS.txt. --- NEWS.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS.txt b/NEWS.txt index 64d7fffbac..8c3785a29a 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -3,7 +3,7 @@ New features: Improvements: - +- Improvements to tagging of files and keyword search results Bugfixes: - Keyword Search: fix when Solr does not cleanly shutdown From cd0940ec973f0a962a99f7df88e63e052c8dc4e9 Mon Sep 17 00:00:00 2001 From: Tim McIver Date: Wed, 3 Apr 2013 16:37:59 -0400 Subject: [PATCH 3/7] Made MediaViewVideoPanel.captureFrames method more robust by checking for errors in return status of calls to play, pause and stop methods of the PlayBin2 object. Also, removed loop that waited for a frame to be captured by using a synchronization lock with timeout to communicate between instance of RGBDataSink.Listener and the captureFrames method. --- .../autopsy/corecomponents/FrameCapture.java | 2 +- .../corecomponents/MediaViewVideoPanel.java | 87 ++++++++++++++++--- 2 files changed, 76 insertions(+), 13 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/FrameCapture.java b/Core/src/org/sleuthkit/autopsy/corecomponents/FrameCapture.java index 1a047eb0d6..77f7462261 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/FrameCapture.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/FrameCapture.java @@ -15,6 +15,6 @@ public interface FrameCapture { * may happen if the video is very short. * @return a list of VideoFrames representing the captured frames */ - List captureFrames(File file, int numFrames); + List captureFrames(File file, int numFrames) throws Exception; } diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewVideoPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewVideoPanel.java index 69a082719b..b73c2cedb0 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewVideoPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewVideoPanel.java @@ -24,7 +24,10 @@ import java.awt.image.BufferedImage; import java.io.IOException; import java.nio.IntBuffer; import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.concurrent.CancellationException; import java.util.concurrent.TimeUnit; import java.util.logging.Level; @@ -41,6 +44,7 @@ import org.gstreamer.ClockTime; import org.gstreamer.Gst; import org.gstreamer.GstException; import org.gstreamer.State; +import org.gstreamer.StateChangeReturn; import org.gstreamer.elements.PlayBin2; import org.gstreamer.elements.RGBDataSink; import org.gstreamer.swing.VideoComponent; @@ -68,6 +72,7 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt private static final Logger logger = Logger.getLogger(MediaViewVideoPanel.class.getName()); private boolean gstInited; private static final long MIN_FRAME_INTERVAL_MILLIS = 500; + private static final long FRAME_CAPTURE_TIMEOUT_MILLIS = 500; //playback private long durationMillis = 0; private VideoProgressWorker videoProgressWorker; @@ -77,6 +82,7 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt private boolean autoTracking = false; // true if the slider is moving automatically private final Object playbinLock = new Object(); // lock for synchronization of gstPlaybin2 player private AbstractFile currentFile; + private Set badVideoFiles = Collections.synchronizedSet(new HashSet()); /** * Creates new form MediaViewVideoPanel @@ -276,15 +282,30 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt return tempFile; } + /** + * @param file a video file from which to capture frames + * @param numFrames the number of frames to capture. These frames will be + * captured at successive intervals given by durationOfVideo/numFrames. If + * this frame interval is less than MIN_FRAME_INTERVAL_MILLIS, then only one + * frame will be captured and returned. + * @return a List of VideoFrames representing the captured frames. + */ @Override - public List captureFrames(java.io.File file, int numFrames) { + public List captureFrames(java.io.File file, int numFrames) throws Exception { List frames = new ArrayList<>(); - FrameCaptureRGBListener rgbListener = new FrameCaptureRGBListener(); - + + Object lock = new Object(); + FrameCaptureRGBListener rgbListener = new FrameCaptureRGBListener(lock); + if (!isInited()) { return frames; } + + // throw exception if this file is known to be problematic + if (badVideoFiles.contains(file)) { + throw new Exception("Cannot capture frames from this file (" + file.getName() + ")."); + } // set up a PlayBin2 object RGBDataSink videoSink = new RGBDataSink("rgb", rgbListener); @@ -293,8 +314,18 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt playbin.setVideoSink(videoSink); // this is necessary to get a valid duration value - playbin.play(); - playbin.pause(); + StateChangeReturn ret = playbin.play(); + if (ret == StateChangeReturn.FAILURE) { + // add this file to the set of known bad ones + badVideoFiles.add(file); + throw new Exception("Problem with video file; problem when attempting to play while obtaining duration."); + } + ret = playbin.pause(); + if (ret == StateChangeReturn.FAILURE) { + // add this file to the set of known bad ones + badVideoFiles.add(file); + throw new Exception("Problem with video file; problem when attempting to pause while obtaining duration."); + } playbin.getState(); // get the duration of the video @@ -315,20 +346,43 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt for (int i = 0; i < numFramesToGet; ++i) { long timeStamp = i * frameInterval; - playbin.pause(); + ret = playbin.pause(); + if (ret == StateChangeReturn.FAILURE) { + // add this file to the set of known bad ones + badVideoFiles.add(file); + throw new Exception("Problem with video file; problem when attempting to pause while capturing a frame."); + } playbin.getState(); + //System.out.println("Seeking to " + timeStamp + "milliseconds."); if (!playbin.seek(timeStamp, unit)) { logger.log(Level.INFO, "There was a problem seeking to " + timeStamp + " " + unit.name().toLowerCase()); } - playbin.play(); - - Image image = null; - while (image == null) { - image = rgbListener.getImage(); + + ret = playbin.play(); + if (ret == StateChangeReturn.FAILURE) { + // add this file to the set of known bad ones + badVideoFiles.add(file); + throw new Exception("Problem with video file; problem when attempting to play while capturing a frame."); } - playbin.stop(); + // wait for FrameCaptureRGBListener to finish + synchronized(lock) { + lock.wait(FRAME_CAPTURE_TIMEOUT_MILLIS); + } + Image image = rgbListener.getImage(); + + ret = playbin.stop(); + if (ret == StateChangeReturn.FAILURE) { + // add this file to the set of known bad ones + badVideoFiles.add(file); + throw new Exception("Problem with video file; problem when attempting to stop while capturing a frame."); + } + + if (image == null) { + logger.log(Level.WARNING, "There was a problem while trying to capture a frame from file " + file.getName()); + continue; + } frames.add(new VideoFrame(image, timeStamp)); } @@ -337,13 +391,22 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt } private class FrameCaptureRGBListener implements RGBDataSink.Listener { + + public FrameCaptureRGBListener(Object waiter) { + this.waiter = waiter; + } private BufferedImage bi; + private final Object waiter; @Override public void rgbFrame(boolean bln, int w, int h, IntBuffer rgbPixels) { bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); bi.setRGB(0, 0, w, h, rgbPixels.array(), 0, w); + System.out.println("Notify waiting object."); + synchronized(waiter) { + waiter.notify(); + } } public Image getImage() { From 10100788f6b445b2ab535b45223221b204d4c075 Mon Sep 17 00:00:00 2001 From: Tim McIver Date: Thu, 4 Apr 2013 14:40:58 -0400 Subject: [PATCH 4/7] Added try/catch around call to lock.wait to better deal with the case that a timeout has occurred. Also reduced the timeout time from 500 ms to 100 ms. --- .../autopsy/corecomponents/MediaViewVideoPanel.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewVideoPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewVideoPanel.java index b73c2cedb0..26a3204796 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewVideoPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewVideoPanel.java @@ -72,7 +72,7 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt private static final Logger logger = Logger.getLogger(MediaViewVideoPanel.class.getName()); private boolean gstInited; private static final long MIN_FRAME_INTERVAL_MILLIS = 500; - private static final long FRAME_CAPTURE_TIMEOUT_MILLIS = 500; + private static final long FRAME_CAPTURE_TIMEOUT_MILLIS = 100; //playback private long durationMillis = 0; private VideoProgressWorker videoProgressWorker; @@ -368,7 +368,11 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt // wait for FrameCaptureRGBListener to finish synchronized(lock) { - lock.wait(FRAME_CAPTURE_TIMEOUT_MILLIS); + try { + lock.wait(FRAME_CAPTURE_TIMEOUT_MILLIS); + } catch (InterruptedException e) { + logger.log(Level.INFO, "Timeout occurred while waiting for frame capture.", e); + } } Image image = rgbListener.getImage(); @@ -403,7 +407,6 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt public void rgbFrame(boolean bln, int w, int h, IntBuffer rgbPixels) { bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); bi.setRGB(0, 0, w, h, rgbPixels.array(), 0, w); - System.out.println("Notify waiting object."); synchronized(waiter) { waiter.notify(); } From 3c4d5cf342cf6b3b519150ea918f42811ddd1d08 Mon Sep 17 00:00:00 2001 From: Tim McIver Date: Thu, 4 Apr 2013 17:39:40 -0400 Subject: [PATCH 5/7] Updates to media player code to handle errors when calling play, pause, stop and setState on PlayBin2 object. An error message will be displayed in the infor label if there is an error. Satisfies requirements of AUT-905. --- .../DataContentViewerMedia.java | 8 +- .../corecomponents/MediaViewVideoPanel.java | 128 ++++++++++++------ 2 files changed, 93 insertions(+), 43 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java index 5da28141a3..1368598dee 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java @@ -27,6 +27,7 @@ import javax.imageio.ImageIO; import org.sleuthkit.autopsy.coreutils.Logger; import javax.swing.SwingUtilities; import org.openide.nodes.Node; +import org.openide.util.Exceptions; import org.openide.util.lookup.ServiceProvider; import org.openide.util.lookup.ServiceProviders; import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer; @@ -111,7 +112,7 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo public void setNode(Node selectedNode) { if (selectedNode == null) { - videoPanel.reset(); + videoPanel.reset(); return; } @@ -126,7 +127,7 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo lastFile = file; } - videoPanel.reset(); + videoPanel.reset(); final Dimension dims = DataContentViewerMedia.this.getSize(); @@ -135,9 +136,8 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo this.switchPanels(false); } else if (videoPanelInited && (containsExt(file.getName(), VIDEOS) || containsExt(file.getName(), AUDIOS))) { - videoPanel.setupVideo(file, dims); - this.switchPanels(true); + switchPanels(true); } } diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewVideoPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewVideoPanel.java index 26a3204796..39e37d9141 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewVideoPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewVideoPanel.java @@ -117,12 +117,13 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt } private void customizeComponents() { - initGst(); + if (!initGst()) { + return; + } progressSlider.setEnabled(false); // disable slider; enable after user plays vid progressSlider.setValue(0); - if (gstInited) { progressSlider.addChangeListener(new ChangeListener() { /** * Should always try to synchronize any call to @@ -135,16 +136,21 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt synchronized (playbinLock) { if (gstPlaybin2 != null && !autoTracking) { State orig = gstPlaybin2.getState(); - gstPlaybin2.pause(); - gstPlaybin2.seek(ClockTime.fromMillis(time)); + if (gstPlaybin2.pause() == StateChangeReturn.FAILURE) { + logger.log(Level.WARNING, "Attempt to call PlayBin2.pause() failed."); + infoLabel.setText("There was a problem setting up the media player."); + return; + } + if (gstPlaybin2.seek(ClockTime.fromMillis(time)) == false) { + logger.log(Level.WARNING, "Attempt to call PlayBin2.seek() failed."); + infoLabel.setText("There was a problem setting up the media player."); + return; + } gstPlaybin2.setState(orig); } } } }); - - - } } private boolean initGst() { @@ -178,6 +184,7 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt * @param dims dimension of the parent window */ void setupVideo(final AbstractFile file, final Dimension dims) { + infoLabel.setText(""); currentFile = file; final boolean deleted = file.isDirNameFlagSet(TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC); if (deleted) { @@ -186,17 +193,18 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt pauseButton.setEnabled(false); progressSlider.setEnabled(false); return; - } else { - try { - String path = file.getUniquePath(); - infoLabel.setText(path); - infoLabel.setToolTipText(path); - pauseButton.setEnabled(true); - progressSlider.setEnabled(true); - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Cannot get unique path of video file"); - } } + + String path = ""; + try { + path = file.getUniquePath(); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Cannot get unique path of video file"); + } + infoLabel.setText(path); + infoLabel.setToolTipText(path); + pauseButton.setEnabled(true); + progressSlider.setEnabled(true); java.io.File ioFile = getJFile(file); @@ -217,7 +225,11 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt videoPanel.setVisible(true); gstPlaybin2.setInputFile(ioFile); - gstPlaybin2.setState(State.READY); + + if (gstPlaybin2.setState(State.READY) == StateChangeReturn.FAILURE) { + logger.log(Level.WARNING, "Attempt to call PlayBin2.setState(State.READY) failed."); + infoLabel.setText("There was a problem setting up the media player."); + } } } @@ -229,12 +241,9 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt @Override public void run() { progressLabel.setText(""); - // infoLabel.setText(""); - } }); - if (!isInited()) { return; } @@ -242,20 +251,23 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt synchronized (playbinLock) { if (gstPlaybin2 != null) { if (gstPlaybin2.isPlaying()) { - gstPlaybin2.stop(); + if (gstPlaybin2.stop() == StateChangeReturn.FAILURE) { + logger.log(Level.WARNING, "Attempt to call PlayBin2.stop() failed."); + infoLabel.setText("There was a problem resetting the media player."); + return; + } + } + if (gstPlaybin2.setState(State.NULL) == StateChangeReturn.FAILURE) { + logger.log(Level.WARNING, "Attempt to call PlayBin2.setState(State.NULL) failed."); + infoLabel.setText("There was a problem resetting the media player."); + return; } - gstPlaybin2.setState(State.NULL); if (gstPlaybin2.getState().equals(State.NULL)) { gstPlaybin2.dispose(); } gstPlaybin2 = null; } gstVideoComponent = null; - //videoComponent.setBackground(Color.BLACK); - //videoComponent.repaint(); - - - //videoPanel.repaint(); } // get rid of any existing videoProgressWorker thread @@ -505,13 +517,31 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt synchronized (playbinLock) { State state = gstPlaybin2.getState(); if (state.equals(State.PLAYING)) { - gstPlaybin2.pause(); + if (gstPlaybin2.pause() == StateChangeReturn.FAILURE) { + logger.log(Level.WARNING, "Attempt to call PlayBin2.pause() failed."); + infoLabel.setText("There was a problem with the media player."); + return; + } pauseButton.setText("►"); - gstPlaybin2.setState(State.PAUSED); + // Is this call necessary considering we just called gstPlaybin2.pause()? + if (gstPlaybin2.setState(State.PAUSED) == StateChangeReturn.FAILURE) { + logger.log(Level.WARNING, "Attempt to call PlayBin2.setState(State.PAUSED) failed."); + infoLabel.setText("There was a problem with the media player."); + return; + } } else if (state.equals(State.PAUSED)) { - gstPlaybin2.play(); + if (gstPlaybin2.play() == StateChangeReturn.FAILURE) { + logger.log(Level.WARNING, "Attempt to call PlayBin2.play() failed."); + infoLabel.setText("There was a problem with the media player."); + return; + } pauseButton.setText("||"); - gstPlaybin2.setState(State.PLAYING); + // Is this call necessary considering we just called gstPlaybin2.play()? + if (gstPlaybin2.setState(State.PLAYING) == StateChangeReturn.FAILURE) { + logger.log(Level.WARNING, "Attempt to call PlayBin2.setState(State.PLAYING) failed."); + infoLabel.setText("There was a problem with the media player."); + return; + } } else if (state.equals(State.READY)) { ExtractMedia em = new ExtractMedia(currentFile, getJFile(currentFile)); em.execute(); @@ -534,6 +564,7 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt private long millisElapsed = 0; private final long INTER_FRAME_PERIOD_MS = 20; private final long END_TIME_MARGIN_MS = 50; + private boolean hadError = false; private boolean isPlayBinReady() { synchronized (playbinLock) { @@ -541,11 +572,18 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt } } - private void resetVideo() { + private void resetVideo() throws Exception { synchronized (playbinLock) { if (gstPlaybin2 != null) { - gstPlaybin2.stop(); - gstPlaybin2.setState(State.READY); // ready to be played again + if (gstPlaybin2.stop() == StateChangeReturn.FAILURE) { + logger.log(Level.WARNING, "Attempt to call PlayBin2.stop() failed."); + infoLabel.setText("There was a problem with the media player."); + } + // ready to be played again + if (gstPlaybin2.setState(State.READY) == StateChangeReturn.FAILURE) { + logger.log(Level.WARNING, "Attempt to call PlayBin2.setState(State.READY) failed."); + infoLabel.setText("There was a problem with the media player."); + } gstPlaybin2.getState(); //NEW } } @@ -682,9 +720,18 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt } ClockTime dur = null; synchronized (playbinLock) { - gstPlaybin2.play(); // must play, then pause and get state to get duration. - gstPlaybin2.pause(); - State state = gstPlaybin2.getState(); + // must play, then pause and get state to get duration. + if (gstPlaybin2.play() == StateChangeReturn.FAILURE) { + logger.log(Level.WARNING, "Attempt to call PlayBin2.play() failed."); + infoLabel.setText("There was a problem with the media player."); + return; + } + if (gstPlaybin2.pause() == StateChangeReturn.FAILURE) { + logger.log(Level.WARNING, "Attempt to call PlayBin2.pause() failed."); + infoLabel.setText("There was a problem with the media player."); + return; + } + gstPlaybin2.getState(); dur = gstPlaybin2.queryDuration(); } duration = dur.toString(); @@ -705,7 +752,10 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt progressSlider.setMinimum(0); synchronized (playbinLock) { - gstPlaybin2.play(); + if (gstPlaybin2.play() == StateChangeReturn.FAILURE) { + logger.log(Level.WARNING, "Attempt to call PlayBin2.play() failed."); + infoLabel.setText("There was a problem with the media player."); + } } pauseButton.setText("||"); videoProgressWorker = new VideoProgressWorker(); From 4b571295dd4d3528301aac33a3105ebad7377c76 Mon Sep 17 00:00:00 2001 From: Tim McIver Date: Fri, 5 Apr 2013 10:32:11 -0400 Subject: [PATCH 6/7] Created a constant for the media player error string and display it in the info JLabel on various gstreamer errors. --- .../corecomponents/MediaViewVideoPanel.java | 31 ++++++++++--------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewVideoPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewVideoPanel.java index 39e37d9141..029898ecbf 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewVideoPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewVideoPanel.java @@ -73,6 +73,7 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt private boolean gstInited; private static final long MIN_FRAME_INTERVAL_MILLIS = 500; private static final long FRAME_CAPTURE_TIMEOUT_MILLIS = 100; + private static final String MEDIA_PLAYER_ERROR_STRING = "The media player cannot process this file."; //playback private long durationMillis = 0; private VideoProgressWorker videoProgressWorker; @@ -138,12 +139,12 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt State orig = gstPlaybin2.getState(); if (gstPlaybin2.pause() == StateChangeReturn.FAILURE) { logger.log(Level.WARNING, "Attempt to call PlayBin2.pause() failed."); - infoLabel.setText("There was a problem setting up the media player."); + infoLabel.setText(MEDIA_PLAYER_ERROR_STRING); return; } if (gstPlaybin2.seek(ClockTime.fromMillis(time)) == false) { logger.log(Level.WARNING, "Attempt to call PlayBin2.seek() failed."); - infoLabel.setText("There was a problem setting up the media player."); + infoLabel.setText(MEDIA_PLAYER_ERROR_STRING); return; } gstPlaybin2.setState(orig); @@ -188,7 +189,7 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt currentFile = file; final boolean deleted = file.isDirNameFlagSet(TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC); if (deleted) { - infoLabel.setText("Playback of deleted videos is not supported, use an external player. "); + infoLabel.setText("Playback of deleted videos is not supported, use an external player."); videoPanel.removeAll(); pauseButton.setEnabled(false); progressSlider.setEnabled(false); @@ -228,7 +229,7 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt if (gstPlaybin2.setState(State.READY) == StateChangeReturn.FAILURE) { logger.log(Level.WARNING, "Attempt to call PlayBin2.setState(State.READY) failed."); - infoLabel.setText("There was a problem setting up the media player."); + infoLabel.setText(MEDIA_PLAYER_ERROR_STRING); } } @@ -253,13 +254,13 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt if (gstPlaybin2.isPlaying()) { if (gstPlaybin2.stop() == StateChangeReturn.FAILURE) { logger.log(Level.WARNING, "Attempt to call PlayBin2.stop() failed."); - infoLabel.setText("There was a problem resetting the media player."); + infoLabel.setText(MEDIA_PLAYER_ERROR_STRING); return; } } if (gstPlaybin2.setState(State.NULL) == StateChangeReturn.FAILURE) { logger.log(Level.WARNING, "Attempt to call PlayBin2.setState(State.NULL) failed."); - infoLabel.setText("There was a problem resetting the media player."); + infoLabel.setText(MEDIA_PLAYER_ERROR_STRING); return; } if (gstPlaybin2.getState().equals(State.NULL)) { @@ -519,27 +520,27 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt if (state.equals(State.PLAYING)) { if (gstPlaybin2.pause() == StateChangeReturn.FAILURE) { logger.log(Level.WARNING, "Attempt to call PlayBin2.pause() failed."); - infoLabel.setText("There was a problem with the media player."); + infoLabel.setText(MEDIA_PLAYER_ERROR_STRING); return; } pauseButton.setText("►"); // Is this call necessary considering we just called gstPlaybin2.pause()? if (gstPlaybin2.setState(State.PAUSED) == StateChangeReturn.FAILURE) { logger.log(Level.WARNING, "Attempt to call PlayBin2.setState(State.PAUSED) failed."); - infoLabel.setText("There was a problem with the media player."); + infoLabel.setText(MEDIA_PLAYER_ERROR_STRING); return; } } else if (state.equals(State.PAUSED)) { if (gstPlaybin2.play() == StateChangeReturn.FAILURE) { logger.log(Level.WARNING, "Attempt to call PlayBin2.play() failed."); - infoLabel.setText("There was a problem with the media player."); + infoLabel.setText(MEDIA_PLAYER_ERROR_STRING); return; } pauseButton.setText("||"); // Is this call necessary considering we just called gstPlaybin2.play()? if (gstPlaybin2.setState(State.PLAYING) == StateChangeReturn.FAILURE) { logger.log(Level.WARNING, "Attempt to call PlayBin2.setState(State.PLAYING) failed."); - infoLabel.setText("There was a problem with the media player."); + infoLabel.setText(MEDIA_PLAYER_ERROR_STRING); return; } } else if (state.equals(State.READY)) { @@ -577,12 +578,12 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt if (gstPlaybin2 != null) { if (gstPlaybin2.stop() == StateChangeReturn.FAILURE) { logger.log(Level.WARNING, "Attempt to call PlayBin2.stop() failed."); - infoLabel.setText("There was a problem with the media player."); + infoLabel.setText(MEDIA_PLAYER_ERROR_STRING); } // ready to be played again if (gstPlaybin2.setState(State.READY) == StateChangeReturn.FAILURE) { logger.log(Level.WARNING, "Attempt to call PlayBin2.setState(State.READY) failed."); - infoLabel.setText("There was a problem with the media player."); + infoLabel.setText(MEDIA_PLAYER_ERROR_STRING); } gstPlaybin2.getState(); //NEW } @@ -723,12 +724,12 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt // must play, then pause and get state to get duration. if (gstPlaybin2.play() == StateChangeReturn.FAILURE) { logger.log(Level.WARNING, "Attempt to call PlayBin2.play() failed."); - infoLabel.setText("There was a problem with the media player."); + infoLabel.setText(MEDIA_PLAYER_ERROR_STRING); return; } if (gstPlaybin2.pause() == StateChangeReturn.FAILURE) { logger.log(Level.WARNING, "Attempt to call PlayBin2.pause() failed."); - infoLabel.setText("There was a problem with the media player."); + infoLabel.setText(MEDIA_PLAYER_ERROR_STRING); return; } gstPlaybin2.getState(); @@ -754,7 +755,7 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt synchronized (playbinLock) { if (gstPlaybin2.play() == StateChangeReturn.FAILURE) { logger.log(Level.WARNING, "Attempt to call PlayBin2.play() failed."); - infoLabel.setText("There was a problem with the media player."); + infoLabel.setText(MEDIA_PLAYER_ERROR_STRING); } } pauseButton.setText("||"); From e2e4e055979c46cda53e3a95c360e13464bdc0d6 Mon Sep 17 00:00:00 2001 From: Tim McIver Date: Fri, 5 Apr 2013 11:22:19 -0400 Subject: [PATCH 7/7] Changed the way problematic video files are tracked: now using a set of strings that are the file names of the bad video files rather than a set of the java.io.Files themselves. --- .../corecomponents/MediaViewVideoPanel.java | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewVideoPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewVideoPanel.java index 029898ecbf..0c48925985 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewVideoPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewVideoPanel.java @@ -83,7 +83,7 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt private boolean autoTracking = false; // true if the slider is moving automatically private final Object playbinLock = new Object(); // lock for synchronization of gstPlaybin2 player private AbstractFile currentFile; - private Set badVideoFiles = Collections.synchronizedSet(new HashSet()); + private Set badVideoFiles = Collections.synchronizedSet(new HashSet()); /** * Creates new form MediaViewVideoPanel @@ -316,7 +316,7 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt } // throw exception if this file is known to be problematic - if (badVideoFiles.contains(file)) { + if (badVideoFiles.contains(file.getName())) { throw new Exception("Cannot capture frames from this file (" + file.getName() + ")."); } @@ -330,13 +330,13 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt StateChangeReturn ret = playbin.play(); if (ret == StateChangeReturn.FAILURE) { // add this file to the set of known bad ones - badVideoFiles.add(file); + badVideoFiles.add(file.getName()); throw new Exception("Problem with video file; problem when attempting to play while obtaining duration."); } ret = playbin.pause(); if (ret == StateChangeReturn.FAILURE) { // add this file to the set of known bad ones - badVideoFiles.add(file); + badVideoFiles.add(file.getName()); throw new Exception("Problem with video file; problem when attempting to pause while obtaining duration."); } playbin.getState(); @@ -362,7 +362,7 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt ret = playbin.pause(); if (ret == StateChangeReturn.FAILURE) { // add this file to the set of known bad ones - badVideoFiles.add(file); + badVideoFiles.add(file.getName()); throw new Exception("Problem with video file; problem when attempting to pause while capturing a frame."); } playbin.getState(); @@ -375,7 +375,7 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt ret = playbin.play(); if (ret == StateChangeReturn.FAILURE) { // add this file to the set of known bad ones - badVideoFiles.add(file); + badVideoFiles.add(file.getName()); throw new Exception("Problem with video file; problem when attempting to play while capturing a frame."); } @@ -392,13 +392,14 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt ret = playbin.stop(); if (ret == StateChangeReturn.FAILURE) { // add this file to the set of known bad ones - badVideoFiles.add(file); + badVideoFiles.add(file.getName()); throw new Exception("Problem with video file; problem when attempting to stop while capturing a frame."); } if (image == null) { logger.log(Level.WARNING, "There was a problem while trying to capture a frame from file " + file.getName()); - continue; + badVideoFiles.add(file.getName()); + break; } frames.add(new VideoFrame(image, timeStamp));