From 60d33b1dcaf086b193957edee7dd5111b82471b3 Mon Sep 17 00:00:00 2001 From: Tim McIver Date: Fri, 21 Dec 2012 16:44:06 -0500 Subject: [PATCH 1/3] Updated DataContentViewerMedia so that elapsed time and total duration display correctly. Changed code to us a format string rather than build up the string with complicated logic. --- .../autopsy/corecomponents/Bundle.properties | 2 +- .../DataContentViewerMedia.form | 18 ++--- .../DataContentViewerMedia.java | 81 ++++++++++--------- 3 files changed, 54 insertions(+), 47 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties index 23067adf05..cf03389e6a 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties @@ -80,7 +80,7 @@ DataContentViewerArtifact.pageLabel.text=Result: AdvancedConfigurationDialog.applyButton.text=OK DataContentViewerMedia.pauseButton.text=\u25ba -DataContentViewerMedia.progressLabel.text=00:00/00:00 +DataContentViewerMedia.progressLabel.text= DataContentViewerString.goToPageLabel.text=Go to Page: DataContentViewerString.goToPageTextField.text= DataContentViewerHex.goToPageTextField.text= diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.form b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.form index a8f4017e03..2dc5d049de 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.form +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.form @@ -16,14 +16,13 @@ - - + + - - - - - + + + + @@ -34,7 +33,7 @@ - + @@ -66,7 +65,7 @@ - + @@ -83,6 +82,7 @@ + diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java index 2857368f12..303a17724a 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java @@ -61,6 +61,7 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo private boolean autoTracking = false; // true if the slider is moving automatically private final Object playbinLock = new Object(); // lock for synchronization of playbin2 player private VideoProgressWorker videoProgressWorker; + private int totalHours, totalMinutes, totalSeconds; /** * Creates new form DataContentViewerVideo @@ -121,7 +122,7 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo videoPanel.setLayout(videoPanelLayout); videoPanelLayout.setHorizontalGroup( videoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 283, Short.MAX_VALUE) + .addGap(0, 0, Short.MAX_VALUE) ); videoPanelLayout.setVerticalGroup( videoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -130,6 +131,7 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo progressSlider.setValue(0); + progressLabel.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT); progressLabel.setText(org.openide.util.NbBundle.getMessage(DataContentViewerMedia.class, "DataContentViewerMedia.progressLabel.text")); // NOI18N javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); @@ -140,10 +142,9 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo .addGroup(layout.createSequentialGroup() .addComponent(pauseButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(progressSlider, javax.swing.GroupLayout.DEFAULT_SIZE, 158, Short.MAX_VALUE) + .addComponent(progressSlider, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(progressLabel) - .addContainerGap()) + .addComponent(progressLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 104, javax.swing.GroupLayout.PREFERRED_SIZE)) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -152,7 +153,7 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) .addComponent(pauseButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(progressSlider, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(progressSlider, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(progressLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) ); }// //GEN-END:initComponents @@ -315,7 +316,7 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo SwingUtilities.invokeLater(new Runnable() { @Override public void run() { - progressLabel.setText(" "); + progressLabel.setText(""); } }); synchronized (playbinLock) { @@ -418,7 +419,7 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo return ExtractMedia.this.cancel(true); } }); - progressLabel.setText("Buffering..."); + progressLabel.setText("Buffering... "); progress.start(); progress.switchToDeterminate(100); try { @@ -464,6 +465,14 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo duration = dur.toString(); durationMillis = dur.toMillis(); + // pick out the total hours, minutes, seconds + long durationSeconds = (int)durationMillis / 1000; + totalHours = (int) durationSeconds / 3600; + durationSeconds -= totalHours * 3600; + totalMinutes = (int) durationSeconds / 60; + durationSeconds -= totalMinutes * 60; + totalSeconds = (int) durationSeconds; + SwingUtilities.invokeLater(new Runnable() { @Override public void run() { @@ -490,13 +499,15 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo private class VideoProgressWorker extends SwingWorker { + private String durationFormat = "%02d:%02d:%02d/%02d:%02d:%02d "; + private boolean isPlayBinReady() { synchronized (playbinLock) { return playbin2 != null && !playbin2.getState().equals(State.NULL); } } - public void restartVideo() { + public void resetVideo() { synchronized (playbinLock) { if (playbin2 != null) { playbin2.stop(); @@ -505,54 +516,50 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo } pauseButton.setText("►"); progressSlider.setValue(0); + + String durationStr = String.format(durationFormat, 0, 0, 0, + totalHours, totalMinutes, totalSeconds); + progressLabel.setText(durationStr); } @Override protected Object doInBackground() throws Exception { - long positionMillis = 0; + long millisElapsed = 0; + int elapsedHours = -1, elapsedMinutes = -1, elapsedSeconds = -1; String finalDuration = ""; - while (positionMillis < durationMillis + while (millisElapsed < durationMillis && isPlayBinReady() && !isCancelled()) { ClockTime pos = null; synchronized (playbinLock) { pos = playbin2.queryPosition(); } - String position = pos.toString(); - positionMillis = pos.toMillis(); - - if (position.length() == 8) { - position = position.substring(3); - } + //String position = pos.toString(); + millisElapsed = pos.toMillis(); - String duration = playbin2.queryDuration().toString(); - if (duration.length() == 8 && duration.substring(0, 3).equals("00:")) { - finalDuration = duration.substring(3); - progressLabel.setText("00:00/" + duration); - } else { - finalDuration = duration; - progressLabel.setText("00:00:00/" + duration); - } - - progressLabel.setText(position + "/" + finalDuration); + // pick out the elapsed hours, minutes, seconds + long secondsElapsed = millisElapsed / 1000; + elapsedHours = (int) secondsElapsed / 3600; + secondsElapsed -= elapsedHours * 3600; + elapsedMinutes = (int) secondsElapsed / 60; + secondsElapsed -= elapsedMinutes * 60; + elapsedSeconds = (int) secondsElapsed; + + String durationStr = String.format(durationFormat, + elapsedHours, elapsedMinutes, elapsedSeconds, + totalHours, totalMinutes, totalSeconds); + + progressLabel.setText(durationStr); autoTracking = true; - progressSlider.setValue((int) positionMillis); + progressSlider.setValue((int) millisElapsed); autoTracking = false; try { Thread.sleep(20); } catch (InterruptedException ex) { - throw ex; + break; } } - if (finalDuration.length() == 5) { - progressLabel.setText("00:00/" + finalDuration); - } else { - progressLabel.setText("00:00:00/" + finalDuration); - } - // If it reached the end - if (progressSlider.getValue() == progressSlider.getMaximum()) { - restartVideo(); - } + resetVideo(); return null; } From b00f4a798af6eeaf16c138b90ef279b41c6a2583 Mon Sep 17 00:00:00 2001 From: Tim McIver Date: Fri, 21 Dec 2012 17:32:54 -0500 Subject: [PATCH 2/3] Disable slider before play button is pressed. Was previously causing a problem when slider was clicked before video played. --- .../DataContentViewerMedia.java | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java index 303a17724a..ef39742887 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java @@ -73,6 +73,7 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo private void customizeComponents() { Gst.init(); + progressSlider.setEnabled(false); // disable slider; enable after user plays vid progressSlider.addChangeListener(new ChangeListener() { /** * Should always try to synchronize any call to @@ -478,14 +479,7 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo public void run() { progressSlider.setMaximum((int) durationMillis); progressSlider.setMinimum(0); - final String finalDuration; - if (duration.length() == 8 && duration.substring(0, 3).equals("00:")) { - finalDuration = duration.substring(3); - progressLabel.setText("00:00/" + duration); - } else { - finalDuration = duration; - progressLabel.setText("00:00:00/" + duration); - } + synchronized (playbinLock) { playbin2.play(); } @@ -524,18 +518,20 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo @Override protected Object doInBackground() throws Exception { + + // enable the slider + progressSlider.setEnabled(true); + long millisElapsed = 0; int elapsedHours = -1, elapsedMinutes = -1, elapsedSeconds = -1; - String finalDuration = ""; while (millisElapsed < durationMillis && isPlayBinReady() && !isCancelled()) { ClockTime pos = null; synchronized (playbinLock) { pos = playbin2.queryPosition(); } - //String position = pos.toString(); millisElapsed = pos.toMillis(); - + // pick out the elapsed hours, minutes, seconds long secondsElapsed = millisElapsed / 1000; elapsedHours = (int) secondsElapsed / 3600; @@ -559,6 +555,9 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo } } + // disable the slider + progressSlider.setEnabled(false); + resetVideo(); return null; From b5954e1fe012557a03b44818f5ef49468c7218e2 Mon Sep 17 00:00:00 2001 From: Tim McIver Date: Wed, 26 Dec 2012 12:33:41 -0500 Subject: [PATCH 3/3] Added code to better determine when video had finished playing. This was needed as some videos' reported time elapsed never became equal to their reported duration causing the play loop to not exit once the video had finished playing. --- .../DataContentViewerMedia.java | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java index ef39742887..837afbaf9c 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java @@ -494,7 +494,10 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo private class VideoProgressWorker extends SwingWorker { private String durationFormat = "%02d:%02d:%02d/%02d:%02d:%02d "; - + private long millisElapsed = 0; + private final long INTER_FRAME_PERIOD_MS = 20; + private final long END_TIME_MARGIN_MS = 50; + private boolean isPlayBinReady() { synchronized (playbinLock) { return playbin2 != null && !playbin2.getState().equals(State.NULL); @@ -515,6 +518,16 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo totalHours, totalMinutes, totalSeconds); progressLabel.setText(durationStr); } + + /** + * @return true while millisElapsed is greater than END_TIME_MARGIN_MS + * from durationMillis. This is used to indicate when the video has ended + * because for some videos the time elapsed never becomes equal to the + * reported duration of the video. + */ + private boolean hasNotEnded() { + return (durationMillis - millisElapsed) > END_TIME_MARGIN_MS; + } @Override protected Object doInBackground() throws Exception { @@ -522,11 +535,10 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo // enable the slider progressSlider.setEnabled(true); - long millisElapsed = 0; int elapsedHours = -1, elapsedMinutes = -1, elapsedSeconds = -1; - while (millisElapsed < durationMillis - && isPlayBinReady() && !isCancelled()) { - ClockTime pos = null; + ClockTime pos = null; + while (hasNotEnded() && isPlayBinReady() && !isCancelled()) { + synchronized (playbinLock) { pos = playbin2.queryPosition(); } @@ -548,13 +560,14 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo autoTracking = true; progressSlider.setValue((int) millisElapsed); autoTracking = false; + try { - Thread.sleep(20); + Thread.sleep(INTER_FRAME_PERIOD_MS); } catch (InterruptedException ex) { break; } } - + // disable the slider progressSlider.setEnabled(false);