mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-17 18:17:43 +00:00
Merge pull request #178 from tmciver-basis/master
Changes for AUT-898 (Frame capture concurrency issue) and an update to NEWS.txt
This commit is contained in:
commit
5c48c12c53
@ -27,6 +27,7 @@ import javax.imageio.ImageIO;
|
|||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
import org.openide.nodes.Node;
|
import org.openide.nodes.Node;
|
||||||
|
import org.openide.util.Exceptions;
|
||||||
import org.openide.util.lookup.ServiceProvider;
|
import org.openide.util.lookup.ServiceProvider;
|
||||||
import org.openide.util.lookup.ServiceProviders;
|
import org.openide.util.lookup.ServiceProviders;
|
||||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer;
|
import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer;
|
||||||
@ -111,7 +112,7 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo
|
|||||||
public void setNode(Node selectedNode) {
|
public void setNode(Node selectedNode) {
|
||||||
|
|
||||||
if (selectedNode == null) {
|
if (selectedNode == null) {
|
||||||
videoPanel.reset();
|
videoPanel.reset();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,7 +127,7 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo
|
|||||||
lastFile = file;
|
lastFile = file;
|
||||||
}
|
}
|
||||||
|
|
||||||
videoPanel.reset();
|
videoPanel.reset();
|
||||||
|
|
||||||
final Dimension dims = DataContentViewerMedia.this.getSize();
|
final Dimension dims = DataContentViewerMedia.this.getSize();
|
||||||
|
|
||||||
@ -135,9 +136,8 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo
|
|||||||
this.switchPanels(false);
|
this.switchPanels(false);
|
||||||
} else if (videoPanelInited
|
} else if (videoPanelInited
|
||||||
&& (containsExt(file.getName(), VIDEOS) || containsExt(file.getName(), AUDIOS))) {
|
&& (containsExt(file.getName(), VIDEOS) || containsExt(file.getName(), AUDIOS))) {
|
||||||
|
|
||||||
videoPanel.setupVideo(file, dims);
|
videoPanel.setupVideo(file, dims);
|
||||||
this.switchPanels(true);
|
switchPanels(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,6 @@ public interface FrameCapture {
|
|||||||
* may happen if the video is very short.
|
* may happen if the video is very short.
|
||||||
* @return a list of VideoFrames representing the captured frames
|
* @return a list of VideoFrames representing the captured frames
|
||||||
*/
|
*/
|
||||||
List<VideoFrame> captureFrames(File file, int numFrames);
|
List<VideoFrame> captureFrames(File file, int numFrames) throws Exception;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -18,13 +18,16 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.corecomponents;
|
package org.sleuthkit.autopsy.corecomponents;
|
||||||
|
|
||||||
import java.awt.Color;
|
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
|
import java.awt.Image;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.IntBuffer;
|
import java.nio.IntBuffer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.CancellationException;
|
import java.util.concurrent.CancellationException;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
@ -41,17 +44,16 @@ import org.gstreamer.ClockTime;
|
|||||||
import org.gstreamer.Gst;
|
import org.gstreamer.Gst;
|
||||||
import org.gstreamer.GstException;
|
import org.gstreamer.GstException;
|
||||||
import org.gstreamer.State;
|
import org.gstreamer.State;
|
||||||
|
import org.gstreamer.StateChangeReturn;
|
||||||
import org.gstreamer.elements.PlayBin2;
|
import org.gstreamer.elements.PlayBin2;
|
||||||
import org.gstreamer.elements.RGBDataSink;
|
import org.gstreamer.elements.RGBDataSink;
|
||||||
import org.gstreamer.swing.VideoComponent;
|
import org.gstreamer.swing.VideoComponent;
|
||||||
import org.netbeans.api.progress.ProgressHandle;
|
import org.netbeans.api.progress.ProgressHandle;
|
||||||
import org.netbeans.api.progress.ProgressHandleFactory;
|
import org.netbeans.api.progress.ProgressHandleFactory;
|
||||||
import org.openide.util.Cancellable;
|
import org.openide.util.Cancellable;
|
||||||
import org.openide.util.Exceptions;
|
|
||||||
import org.openide.util.lookup.ServiceProvider;
|
import org.openide.util.lookup.ServiceProvider;
|
||||||
import org.openide.util.lookup.ServiceProviders;
|
import org.openide.util.lookup.ServiceProviders;
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer;
|
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||||
import org.sleuthkit.autopsy.datamodel.ContentUtils;
|
import org.sleuthkit.autopsy.datamodel.ContentUtils;
|
||||||
@ -69,9 +71,9 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt
|
|||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(MediaViewVideoPanel.class.getName());
|
private static final Logger logger = Logger.getLogger(MediaViewVideoPanel.class.getName());
|
||||||
private boolean gstInited;
|
private boolean gstInited;
|
||||||
//frame capture
|
|
||||||
private BufferedImage currentImage = null;
|
|
||||||
private static final long MIN_FRAME_INTERVAL_MILLIS = 500;
|
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
|
//playback
|
||||||
private long durationMillis = 0;
|
private long durationMillis = 0;
|
||||||
private VideoProgressWorker videoProgressWorker;
|
private VideoProgressWorker videoProgressWorker;
|
||||||
@ -81,6 +83,7 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt
|
|||||||
private boolean autoTracking = false; // true if the slider is moving automatically
|
private boolean autoTracking = false; // true if the slider is moving automatically
|
||||||
private final Object playbinLock = new Object(); // lock for synchronization of gstPlaybin2 player
|
private final Object playbinLock = new Object(); // lock for synchronization of gstPlaybin2 player
|
||||||
private AbstractFile currentFile;
|
private AbstractFile currentFile;
|
||||||
|
private Set<String> badVideoFiles = Collections.synchronizedSet(new HashSet<String>());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates new form MediaViewVideoPanel
|
* Creates new form MediaViewVideoPanel
|
||||||
@ -115,12 +118,13 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void customizeComponents() {
|
private void customizeComponents() {
|
||||||
initGst();
|
if (!initGst()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
progressSlider.setEnabled(false); // disable slider; enable after user plays vid
|
progressSlider.setEnabled(false); // disable slider; enable after user plays vid
|
||||||
progressSlider.setValue(0);
|
progressSlider.setValue(0);
|
||||||
|
|
||||||
if (gstInited) {
|
|
||||||
progressSlider.addChangeListener(new ChangeListener() {
|
progressSlider.addChangeListener(new ChangeListener() {
|
||||||
/**
|
/**
|
||||||
* Should always try to synchronize any call to
|
* Should always try to synchronize any call to
|
||||||
@ -133,16 +137,21 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt
|
|||||||
synchronized (playbinLock) {
|
synchronized (playbinLock) {
|
||||||
if (gstPlaybin2 != null && !autoTracking) {
|
if (gstPlaybin2 != null && !autoTracking) {
|
||||||
State orig = gstPlaybin2.getState();
|
State orig = gstPlaybin2.getState();
|
||||||
gstPlaybin2.pause();
|
if (gstPlaybin2.pause() == StateChangeReturn.FAILURE) {
|
||||||
gstPlaybin2.seek(ClockTime.fromMillis(time));
|
logger.log(Level.WARNING, "Attempt to call PlayBin2.pause() failed.");
|
||||||
|
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(MEDIA_PLAYER_ERROR_STRING);
|
||||||
|
return;
|
||||||
|
}
|
||||||
gstPlaybin2.setState(orig);
|
gstPlaybin2.setState(orig);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean initGst() {
|
private boolean initGst() {
|
||||||
@ -176,25 +185,27 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt
|
|||||||
* @param dims dimension of the parent window
|
* @param dims dimension of the parent window
|
||||||
*/
|
*/
|
||||||
void setupVideo(final AbstractFile file, final Dimension dims) {
|
void setupVideo(final AbstractFile file, final Dimension dims) {
|
||||||
|
infoLabel.setText("");
|
||||||
currentFile = file;
|
currentFile = file;
|
||||||
final boolean deleted = file.isDirNameFlagSet(TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC);
|
final boolean deleted = file.isDirNameFlagSet(TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC);
|
||||||
if (deleted) {
|
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();
|
videoPanel.removeAll();
|
||||||
pauseButton.setEnabled(false);
|
pauseButton.setEnabled(false);
|
||||||
progressSlider.setEnabled(false);
|
progressSlider.setEnabled(false);
|
||||||
return;
|
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);
|
java.io.File ioFile = getJFile(file);
|
||||||
|
|
||||||
@ -215,7 +226,11 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt
|
|||||||
videoPanel.setVisible(true);
|
videoPanel.setVisible(true);
|
||||||
|
|
||||||
gstPlaybin2.setInputFile(ioFile);
|
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(MEDIA_PLAYER_ERROR_STRING);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -227,12 +242,9 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
progressLabel.setText("");
|
progressLabel.setText("");
|
||||||
// infoLabel.setText("");
|
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
if (!isInited()) {
|
if (!isInited()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -240,20 +252,23 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt
|
|||||||
synchronized (playbinLock) {
|
synchronized (playbinLock) {
|
||||||
if (gstPlaybin2 != null) {
|
if (gstPlaybin2 != null) {
|
||||||
if (gstPlaybin2.isPlaying()) {
|
if (gstPlaybin2.isPlaying()) {
|
||||||
gstPlaybin2.stop();
|
if (gstPlaybin2.stop() == StateChangeReturn.FAILURE) {
|
||||||
|
logger.log(Level.WARNING, "Attempt to call PlayBin2.stop() failed.");
|
||||||
|
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(MEDIA_PLAYER_ERROR_STRING);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
gstPlaybin2.setState(State.NULL);
|
|
||||||
if (gstPlaybin2.getState().equals(State.NULL)) {
|
if (gstPlaybin2.getState().equals(State.NULL)) {
|
||||||
gstPlaybin2.dispose();
|
gstPlaybin2.dispose();
|
||||||
}
|
}
|
||||||
gstPlaybin2 = null;
|
gstPlaybin2 = null;
|
||||||
}
|
}
|
||||||
gstVideoComponent = null;
|
gstVideoComponent = null;
|
||||||
//videoComponent.setBackground(Color.BLACK);
|
|
||||||
//videoComponent.repaint();
|
|
||||||
|
|
||||||
|
|
||||||
//videoPanel.repaint();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// get rid of any existing videoProgressWorker thread
|
// get rid of any existing videoProgressWorker thread
|
||||||
@ -280,34 +295,50 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt
|
|||||||
return tempFile;
|
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
|
@Override
|
||||||
public List<VideoFrame> captureFrames(java.io.File file, int numFrames) {
|
public List<VideoFrame> captureFrames(java.io.File file, int numFrames) throws Exception {
|
||||||
|
|
||||||
List<VideoFrame> frames = new ArrayList<>();
|
List<VideoFrame> frames = new ArrayList<>();
|
||||||
|
|
||||||
|
Object lock = new Object();
|
||||||
|
FrameCaptureRGBListener rgbListener = new FrameCaptureRGBListener(lock);
|
||||||
|
|
||||||
if (!isInited()) {
|
if (!isInited()) {
|
||||||
return frames;
|
return frames;
|
||||||
}
|
}
|
||||||
|
|
||||||
RGBDataSink.Listener listener1 = new RGBDataSink.Listener() {
|
// throw exception if this file is known to be problematic
|
||||||
@Override
|
if (badVideoFiles.contains(file.getName())) {
|
||||||
public void rgbFrame(boolean bln, int w, int h, IntBuffer rgbPixels) {
|
throw new Exception("Cannot capture frames from this file (" + file.getName() + ").");
|
||||||
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
|
// set up a PlayBin2 object
|
||||||
RGBDataSink videoSink = new RGBDataSink("rgb", listener1);
|
RGBDataSink videoSink = new RGBDataSink("rgb", rgbListener);
|
||||||
PlayBin2 playbin = new PlayBin2("VideoFrameCapture");
|
PlayBin2 playbin = new PlayBin2("VideoFrameCapture");
|
||||||
playbin.setInputFile(file);
|
playbin.setInputFile(file);
|
||||||
playbin.setVideoSink(videoSink);
|
playbin.setVideoSink(videoSink);
|
||||||
|
|
||||||
// this is necessary to get a valid duration value
|
// this is necessary to get a valid duration value
|
||||||
playbin.play();
|
StateChangeReturn ret = playbin.play();
|
||||||
playbin.pause();
|
if (ret == StateChangeReturn.FAILURE) {
|
||||||
|
// add this file to the set of known bad ones
|
||||||
|
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.getName());
|
||||||
|
throw new Exception("Problem with video file; problem when attempting to pause while obtaining duration.");
|
||||||
|
}
|
||||||
playbin.getState();
|
playbin.getState();
|
||||||
|
|
||||||
// get the duration of the video
|
// get the duration of the video
|
||||||
@ -317,7 +348,7 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt
|
|||||||
return frames;
|
return frames;
|
||||||
}
|
}
|
||||||
|
|
||||||
// create a list of timestamps at which to get frames
|
// calculate the number of frames to capture
|
||||||
int numFramesToGet = numFrames;
|
int numFramesToGet = numFrames;
|
||||||
long frameInterval = myDurationMillis / numFrames;
|
long frameInterval = myDurationMillis / numFrames;
|
||||||
if (frameInterval < MIN_FRAME_INTERVAL_MILLIS) {
|
if (frameInterval < MIN_FRAME_INTERVAL_MILLIS) {
|
||||||
@ -328,26 +359,80 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt
|
|||||||
for (int i = 0; i < numFramesToGet; ++i) {
|
for (int i = 0; i < numFramesToGet; ++i) {
|
||||||
long timeStamp = i * frameInterval;
|
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.getName());
|
||||||
|
throw new Exception("Problem with video file; problem when attempting to pause while capturing a frame.");
|
||||||
|
}
|
||||||
playbin.getState();
|
playbin.getState();
|
||||||
|
|
||||||
currentImage = null;
|
//System.out.println("Seeking to " + timeStamp + "milliseconds.");
|
||||||
if (!playbin.seek(timeStamp, unit)) {
|
if (!playbin.seek(timeStamp, unit)) {
|
||||||
logger.log(Level.INFO, "There was a problem seeking to " + timeStamp + " " + unit.name().toLowerCase());
|
logger.log(Level.INFO, "There was a problem seeking to " + timeStamp + " " + unit.name().toLowerCase());
|
||||||
}
|
}
|
||||||
playbin.play();
|
|
||||||
|
ret = playbin.play();
|
||||||
while (currentImage == null) {
|
if (ret == StateChangeReturn.FAILURE) {
|
||||||
System.out.flush(); // not sure why this is needed
|
// add this file to the set of known bad ones
|
||||||
|
badVideoFiles.add(file.getName());
|
||||||
|
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) {
|
||||||
|
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();
|
||||||
|
|
||||||
frames.add(new VideoFrame(currentImage, timeStamp));
|
ret = playbin.stop();
|
||||||
|
if (ret == StateChangeReturn.FAILURE) {
|
||||||
|
// add this file to the set of known bad ones
|
||||||
|
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());
|
||||||
|
badVideoFiles.add(file.getName());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
frames.add(new VideoFrame(image, timeStamp));
|
||||||
}
|
}
|
||||||
|
|
||||||
return frames;
|
return frames;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
synchronized(waiter) {
|
||||||
|
waiter.notify();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Image getImage() {
|
||||||
|
Image image = bi;
|
||||||
|
bi = null;
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is called from within the constructor to initialize the form.
|
* This method is called from within the constructor to initialize the form.
|
||||||
@ -434,13 +519,31 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt
|
|||||||
synchronized (playbinLock) {
|
synchronized (playbinLock) {
|
||||||
State state = gstPlaybin2.getState();
|
State state = gstPlaybin2.getState();
|
||||||
if (state.equals(State.PLAYING)) {
|
if (state.equals(State.PLAYING)) {
|
||||||
gstPlaybin2.pause();
|
if (gstPlaybin2.pause() == StateChangeReturn.FAILURE) {
|
||||||
|
logger.log(Level.WARNING, "Attempt to call PlayBin2.pause() failed.");
|
||||||
|
infoLabel.setText(MEDIA_PLAYER_ERROR_STRING);
|
||||||
|
return;
|
||||||
|
}
|
||||||
pauseButton.setText("►");
|
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(MEDIA_PLAYER_ERROR_STRING);
|
||||||
|
return;
|
||||||
|
}
|
||||||
} else if (state.equals(State.PAUSED)) {
|
} 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(MEDIA_PLAYER_ERROR_STRING);
|
||||||
|
return;
|
||||||
|
}
|
||||||
pauseButton.setText("||");
|
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(MEDIA_PLAYER_ERROR_STRING);
|
||||||
|
return;
|
||||||
|
}
|
||||||
} else if (state.equals(State.READY)) {
|
} else if (state.equals(State.READY)) {
|
||||||
ExtractMedia em = new ExtractMedia(currentFile, getJFile(currentFile));
|
ExtractMedia em = new ExtractMedia(currentFile, getJFile(currentFile));
|
||||||
em.execute();
|
em.execute();
|
||||||
@ -463,6 +566,7 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt
|
|||||||
private long millisElapsed = 0;
|
private long millisElapsed = 0;
|
||||||
private final long INTER_FRAME_PERIOD_MS = 20;
|
private final long INTER_FRAME_PERIOD_MS = 20;
|
||||||
private final long END_TIME_MARGIN_MS = 50;
|
private final long END_TIME_MARGIN_MS = 50;
|
||||||
|
private boolean hadError = false;
|
||||||
|
|
||||||
private boolean isPlayBinReady() {
|
private boolean isPlayBinReady() {
|
||||||
synchronized (playbinLock) {
|
synchronized (playbinLock) {
|
||||||
@ -470,11 +574,18 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void resetVideo() {
|
private void resetVideo() throws Exception {
|
||||||
synchronized (playbinLock) {
|
synchronized (playbinLock) {
|
||||||
if (gstPlaybin2 != null) {
|
if (gstPlaybin2 != null) {
|
||||||
gstPlaybin2.stop();
|
if (gstPlaybin2.stop() == StateChangeReturn.FAILURE) {
|
||||||
gstPlaybin2.setState(State.READY); // ready to be played again
|
logger.log(Level.WARNING, "Attempt to call PlayBin2.stop() failed.");
|
||||||
|
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(MEDIA_PLAYER_ERROR_STRING);
|
||||||
|
}
|
||||||
gstPlaybin2.getState(); //NEW
|
gstPlaybin2.getState(); //NEW
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -611,9 +722,18 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt
|
|||||||
}
|
}
|
||||||
ClockTime dur = null;
|
ClockTime dur = null;
|
||||||
synchronized (playbinLock) {
|
synchronized (playbinLock) {
|
||||||
gstPlaybin2.play(); // must play, then pause and get state to get duration.
|
// must play, then pause and get state to get duration.
|
||||||
gstPlaybin2.pause();
|
if (gstPlaybin2.play() == StateChangeReturn.FAILURE) {
|
||||||
State state = gstPlaybin2.getState();
|
logger.log(Level.WARNING, "Attempt to call PlayBin2.play() failed.");
|
||||||
|
infoLabel.setText(MEDIA_PLAYER_ERROR_STRING);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (gstPlaybin2.pause() == StateChangeReturn.FAILURE) {
|
||||||
|
logger.log(Level.WARNING, "Attempt to call PlayBin2.pause() failed.");
|
||||||
|
infoLabel.setText(MEDIA_PLAYER_ERROR_STRING);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
gstPlaybin2.getState();
|
||||||
dur = gstPlaybin2.queryDuration();
|
dur = gstPlaybin2.queryDuration();
|
||||||
}
|
}
|
||||||
duration = dur.toString();
|
duration = dur.toString();
|
||||||
@ -634,7 +754,10 @@ public class MediaViewVideoPanel extends javax.swing.JPanel implements FrameCapt
|
|||||||
progressSlider.setMinimum(0);
|
progressSlider.setMinimum(0);
|
||||||
|
|
||||||
synchronized (playbinLock) {
|
synchronized (playbinLock) {
|
||||||
gstPlaybin2.play();
|
if (gstPlaybin2.play() == StateChangeReturn.FAILURE) {
|
||||||
|
logger.log(Level.WARNING, "Attempt to call PlayBin2.play() failed.");
|
||||||
|
infoLabel.setText(MEDIA_PLAYER_ERROR_STRING);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pauseButton.setText("||");
|
pauseButton.setText("||");
|
||||||
videoProgressWorker = new VideoProgressWorker();
|
videoProgressWorker = new VideoProgressWorker();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user