Package org.sleuthkit.autopsy.corecomponents

Source Code of org.sleuthkit.autopsy.corecomponents.FXVideoPanel$MediaPane$TimeListener

/*
* Autopsy Forensic Browser
*
* Copyright 2013 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.corecomponents;

import java.awt.Dimension;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CancellationException;
import java.util.logging.Level;
import javafx.application.Platform;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.embed.swing.JFXPanel;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.scene.media.Media;
import javafx.scene.media.MediaException;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaPlayer.Status;
import static javafx.scene.media.MediaPlayer.Status.PAUSED;
import static javafx.scene.media.MediaPlayer.Status.PLAYING;
import static javafx.scene.media.MediaPlayer.Status.READY;
import static javafx.scene.media.MediaPlayer.Status.STOPPED;
import javafx.scene.media.MediaView;
import javafx.util.Duration;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import org.netbeans.api.progress.ProgressHandle;
import org.netbeans.api.progress.ProgressHandleFactory;
import org.openide.util.Cancellable;
import org.openide.util.NbBundle;
import org.openide.util.lookup.ServiceProvider;
import org.openide.util.lookup.ServiceProviders;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.core.Installer;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.ContentUtils;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskData;

/**
* Video viewer part of the Media View layered pane.
*/
@ServiceProviders(value = {
    @ServiceProvider(service = FrameCapture.class)
})
public class FXVideoPanel extends MediaViewVideoPanel {

    private static final String[] EXTENSIONS = new String[]{".mov", ".m4v", ".flv", ".mp4", ".mpg", ".mpeg"}; //NON-NLS
    private static final List<String> MIMETYPES = Arrays.asList("audio/x-aiff", "video/x-javafx", "video/x-flv", "application/vnd.apple.mpegurl", " audio/mpegurl", "audio/mpeg", "video/mp4", "audio/x-m4a", "video/x-m4v", "audio/x-wav"); //NON-NLS
    private static final Logger logger = Logger.getLogger(MediaViewVideoPanel.class.getName());

    private boolean fxInited = false;

    // FX Components
    private MediaPane mediaPane;

    // Current media content representations
    private AbstractFile currentFile;

    // FX UI Components
    private JFXPanel videoComponent;

    /**
     * Creates new form MediaViewVideoPanel
     */
    public FXVideoPanel() {
        fxInited = Installer.isJavaFxInited();
        initComponents();
        if (fxInited) {
            setupFx();
        }
    }

    public JPanel getVideoPanel() {
        return this;
    }

    private void setupFx() {
        Platform.runLater(new Runnable() {
            @Override
            public void run() {
                videoComponent = new JFXPanel();
                mediaPane = new MediaPane();
                Scene fxScene = new Scene(mediaPane);
                videoComponent.setScene(fxScene);

                SwingUtilities.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        add(videoComponent);
                    }
                });
            }
        });
    }

    @Override
    void setupVideo(final AbstractFile file, final Dimension dims) {
        if (file.equals(currentFile)) {
            return;
        }
        if (!Case.isCaseOpen()) {
            //handle in-between condition when case is being closed
            //and an image was previously selected
            return;
        }
        reset();
        currentFile = file;
        final boolean deleted = file.isDirNameFlagSet(TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC);
        if (deleted) {
            mediaPane.setInfoLabelText(NbBundle.getMessage(this.getClass(), "FXVideoPanel.mediaPane.infoLabel"));
            removeAll();
            return;
        }

        String path = "";
        try {
            path = file.getUniquePath();
        } catch (TskCoreException ex) {
            logger.log(Level.SEVERE, "Cannot get unique path of video file"); //NON-NLS
        }
        mediaPane.setInfoLabelText(path);
        mediaPane.setInfoLabelToolTipText(path);

        ExtractMedia em = new ExtractMedia(currentFile, getJFile(currentFile));
        em.execute();

        mediaPane.setFit(dims);
    }

    @Override
    void reset() {
        Platform.runLater(new Runnable() {
            @Override
            public void run() {
                if (mediaPane != null) {
                    mediaPane.reset();
                }
            }
        });
        currentFile = null;
    }

    private java.io.File getJFile(AbstractFile file) {
        // Get the temp folder path of the case
        String tempPath = Case.getCurrentCase().getTempDirectory();
        String name = file.getName();
        int extStart = name.lastIndexOf(".");
        String ext = "";
        if (extStart != -1) {
            ext = name.substring(extStart, name.length()).toLowerCase();
        }
        tempPath = tempPath + java.io.File.separator + file.getId() + ext;

        java.io.File tempFile = new java.io.File(tempPath);
        return tempFile;
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        setBackground(new java.awt.Color(0, 0, 0));
        setLayout(new javax.swing.BoxLayout(this, javax.swing.BoxLayout.LINE_AXIS));
    }// </editor-fold>//GEN-END:initComponents
    // Variables declaration - do not modify//GEN-BEGIN:variables
    // End of variables declaration//GEN-END:variables

    @Override
    public boolean isInited() {
        return fxInited;
    }

    /**
     * Thread that extracts Media from a Sleuthkit file representation to a
     * Java file representation that the Media Player can take as input.
     */
    private class ExtractMedia extends SwingWorker<Object, Void> {

        private ProgressHandle progress;

        boolean success = false;

        private AbstractFile sFile;

        private java.io.File jFile;

        private long extractedBytes;

        ExtractMedia(org.sleuthkit.datamodel.AbstractFile sFile, java.io.File jFile) {
            this.sFile = sFile;
            this.jFile = jFile;
        }

        public long getExtractedBytes() {
            return extractedBytes;
        }

        /**
         * Get the URI of the media file.
         *
         * @return the URI of the media file.
         */
        public String getMediaUri() {
            return Paths.get(jFile.getAbsolutePath()).toUri().toString();
        }

        @Override
        protected Object doInBackground() throws Exception {
            success = false;
            progress = ProgressHandleFactory.createHandle(
                    NbBundle.getMessage(this.getClass(), "FXVideoPanel.progress.bufferingFile", sFile.getName()),
                    new Cancellable() {
                        @Override
                        public boolean cancel() {
                            return ExtractMedia.this.cancel(true);
                        }
                    });
            mediaPane.setProgressLabelText(NbBundle.getMessage(this.getClass(), "FXVideoPanel.progressLabel.buffering"));
            progress.start();
            progress.switchToDeterminate(100);
            try {
                extractedBytes = ContentUtils.writeToFile(sFile, jFile, progress, this, true);
            } catch (IOException ex) {
                logger.log(Level.WARNING, "Error buffering file", ex); //NON-NLS
            }
            logger.log(Level.INFO, "Done buffering: " + jFile.getName()); //NON-NLS
            success = true;
            return null;
        }

        /* clean up or start the worker threads */
        @Override
        protected void done() {
            mediaPane.setProgressLabelText("");
            try {
                super.get(); //block and get all exceptions thrown while doInBackground()
            } catch (CancellationException ex) {
                logger.log(Level.INFO, "Media buffering was canceled."); //NON-NLS
                mediaPane.setProgressLabelText("media buffering was canceled");
            } catch (InterruptedException ex) {
                logger.log(Level.INFO, "Media buffering was interrupted."); //NON-NLS
                mediaPane.setProgressLabelText("media buffering was interrupted");
            } catch (Exception ex) {
                logger.log(Level.SEVERE, "Fatal error during media buffering.", ex); //NON-NLS
                mediaPane.setProgressLabelText("Error writing video to disk");
            } finally {
                progress.finish();
                if (!this.isCancelled()) {
                    logger.log(Level.INFO, "ExtractMedia in done: " + jFile.getName()); //NON-NLS
                    try {
                        Platform.runLater(new Runnable() {
                            @Override
                            public void run() {
                                mediaPane.prepareMedia(getMediaUri());
                            }
                        });
                    } catch (MediaException e) {
                        logger.log(Level.WARNING, "something went wrong with javafx", e); //NON-NLS
                        reset();
                        mediaPane.setInfoLabelText(e.getMessage());
                        return;
                    }
                }
            }
        }
    }

    /**
     * The JavaFX Component that contains the Media and it's Controls.
     *
     */
    private class MediaPane extends BorderPane {

        private MediaPlayer mediaPlayer;

        private MediaView mediaView;

        /** The Duration of the media. * */
        private Duration duration;

        /** The container for the media controls. * */
        private HBox mediaTools;

        /** The container for the media video output. * */
        private HBox mediaViewPane;

        private VBox controlPanel;

        private Slider progressSlider;

        private Button pauseButton;

        private Button stopButton;

        private Label progressLabel;

        private Label infoLabel;

        private int totalHours;

        private int totalMinutes;

        private int totalSeconds;

        private String durationFormat = "%02d:%02d:%02d/%02d:%02d:%02d  "; //NON-NLS

        /** The EventHandler for MediaPlayer.onReady(). * */
        private final ReadyListener READY_LISTENER = new ReadyListener();

        /** The EventHandler for MediaPlayer.onEndOfMedia(). * */
        private final EndOfMediaListener END_LISTENER = new EndOfMediaListener();

        /** The EventHandler for the CurrentTime property of the MediaPlayer. * */
        private final TimeListener TIME_LISTENER = new TimeListener();

        /** The EventHandler for MediaPlayer.onPause and MediaPlayer.onStop. * */
        private final NotPlayListener NOT_PLAY_LISTENER = new NotPlayListener();

        /** The EventHandler for MediaPlayer.onPlay. * */
        private final PlayListener PLAY_LISTENER = new PlayListener();

        private static final String PLAY_TEXT = "â–º";

        private static final String PAUSE_TEXT = "||";

        private static final String STOP_TEXT = "X"; //NON-NLS

        public MediaPane() {
            // Video Display
            mediaViewPane = new HBox();
            mediaViewPane.setStyle("-fx-background-color: black"); //NON-NLS
            mediaViewPane.setAlignment(Pos.CENTER);
            mediaView = new MediaView();
            mediaViewPane.getChildren().add(mediaView);
            setCenter(mediaViewPane);

            // Media Controls
            controlPanel = new VBox();
            mediaTools = new HBox();
            mediaTools.setAlignment(Pos.CENTER);
            mediaTools.setPadding(new Insets(5, 10, 5, 10));

            pauseButton = new Button(PLAY_TEXT);
            stopButton = new Button(STOP_TEXT);
            mediaTools.getChildren().add(pauseButton);
            mediaTools.getChildren().add(new Label("  "));
            mediaTools.getChildren().add(stopButton);
            mediaTools.getChildren().add(new Label("  "));
            progressSlider = new Slider();
            HBox.setHgrow(progressSlider, Priority.ALWAYS);
            progressSlider.setMinWidth(50);
            progressSlider.setMaxWidth(Double.MAX_VALUE);
            mediaTools.getChildren().add(progressSlider);
            progressLabel = new Label();
            progressLabel.setPrefWidth(135);
            progressLabel.setMinWidth(135);
            mediaTools.getChildren().add(progressLabel);

            controlPanel.getChildren().add(mediaTools);
            controlPanel.setStyle("-fx-background-color: white"); //NON-NLS
            infoLabel = new Label("");
            controlPanel.getChildren().add(infoLabel);
            setBottom(controlPanel);
            setProgressActionListeners();
        }

        /**
         * Setup the MediaPane for media playback. Run on the JavaFx Thread.
         *
         *
         * @param mediaUri the URI of the media
         */
        public void prepareMedia(String mediaUri) {
            try {
                mediaPlayer = createMediaPlayer(mediaUri);
                mediaView.setMediaPlayer(mediaPlayer);
            } catch (MediaException ex) {
                this.setProgressLabelText("");
                this.setInfoLabelText(NbBundle.getMessage(this.getClass(), "FXVideoPanel.media.unsupportedFormat"));
            }
        }

        /**
         * Reset this MediaPane.
         *
         */
        public void reset() {
            if (mediaPlayer != null) {
                setInfoLabelText("");
                if (mediaPlayer.getStatus() == Status.PLAYING) {
                    mediaPlayer.stop();
                }
                mediaPlayer = null;
                mediaView.setMediaPlayer(null);
            }
            resetProgress();
        }

        /**
         * Set the Information Label of this MediaPane.
         *
         * @param text
         */
        public void setInfoLabelText(final String text) {
            logger.log(Level.INFO, "Setting Info Label Text: " + text); //NON-NLS
            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    infoLabel.setText(text);
                }
            });
        }

        /**
         * Set the size of the MediaPane and it's components.
         *
         * @param dims the current dimensions of the DataContentViewer
         */
        public void setFit(final Dimension dims) {
            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    setPrefSize(dims.getWidth(), dims.getHeight());
                    // Set the Video output to fit the size allocated for it. give an
                    // extra few px to ensure the info label will be shown
                    mediaView.setFitHeight(dims.getHeight() - controlPanel.getHeight());
                }
            });
        }

        /**
         * Set the action listeners for the pause button and progress slider.
         */
        private void setProgressActionListeners() {
            pauseButton.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent e) {
                    Status status = mediaPlayer.getStatus();

                    switch (status) {
                        // If playing, pause
                        case PLAYING:
                            mediaPlayer.pause();
                            break;
                        // If ready, paused or stopped, continue playing
                        case READY:
                        case PAUSED:
                        case STOPPED:
                            mediaPlayer.play();
                            break;
                        default:
                            logger.log(Level.INFO, "MediaPlayer in unexpected state: " + status.toString()); //NON-NLS
                            // If the MediaPlayer is in an unexpected state, stop playback.
                            mediaPlayer.stop();
                            setInfoLabelText(NbBundle.getMessage(this.getClass(),
                                                                 "FXVideoPanel.pauseButton.infoLabel.playbackErr"));
                            break;
                    }
                }
            });

            stopButton.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent e) {
                    mediaPlayer.stop();
                }
            });

            progressSlider.valueProperty().addListener(new InvalidationListener() {
                @Override
                public void invalidated(Observable o) {
                    if (progressSlider.isValueChanging()) {
                        mediaPlayer.seek(duration.multiply(progressSlider.getValue() / 100.0));
                    }
                }
            });
        }

        /**
         * Reset the progress label and slider to zero.
         */
        private void resetProgress() {
            totalHours = 0;
            totalMinutes = 0;
            totalSeconds = 0;
            progressSlider.setValue(0.0);
            updateTime(Duration.ZERO);
        }

        /**
         * Construct a MediaPlayer from the given Media URI.
         *
         * Also adds the necessary listeners to MediaPlayer events.
         *
         * @param mediaUri the location of the media.
         *
         * @return a MediaPlayer
         */
        private MediaPlayer createMediaPlayer(String mediaUri) {
            Media media = new Media(mediaUri);

            MediaPlayer player = new MediaPlayer(media);
            player.setOnReady(READY_LISTENER);
            player.setOnPaused(NOT_PLAY_LISTENER);
            player.setOnStopped(NOT_PLAY_LISTENER);
            player.setOnPlaying(PLAY_LISTENER);
            player.setOnEndOfMedia(END_LISTENER);

            player.currentTimeProperty().addListener(TIME_LISTENER);

            return player;
        }

        /**
         * Update the progress slider and label with the current time of the
         * media.
         */
        private void updateProgress() {
            Duration currentTime = mediaPlayer.getCurrentTime();
            updateSlider(currentTime);
            updateTime(currentTime);
        }

        /**
         * Update the slider with the current time.
         *
         * @param currentTime
         */
        private void updateSlider(Duration currentTime) {
            if (progressSlider != null) {
                progressSlider.setDisable(currentTime.isUnknown());
                if (!progressSlider.isDisabled() && duration.greaterThan(Duration.ZERO)
                        && !progressSlider.isValueChanging()) {
                    progressSlider.setValue(currentTime.divide(duration.toMillis()).toMillis() * 100.0);
                }
            }
        }

        /**
         * Update the progress label with the current time.
         *
         * @param currentTime
         */
        private void updateTime(Duration currentTime) {
            long millisElapsed = (long) currentTime.toMillis();

            long elapsedHours, elapsedMinutes, elapsedSeconds;
            // 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);
            setProgressLabelText(durationStr);
        }

        /**
         * Update the progress label to show the text.
         *
         * @param text
         */
        private void setProgressLabelText(final String text) {
            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    progressLabel.setText(text);
                }
            });
        }

        private void setInfoLabelToolTipText(final String text) {
            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    infoLabel.setTooltip(new Tooltip(text));
                }
            });
        }

        /**
         * Responds to MediaPlayer onReady events.
         *
         * Updates the progress label with the duration of the media.
         */
        private class ReadyListener implements Runnable {

            @Override
            public void run() {
                duration = mediaPlayer.getMedia().getDuration();
                long durationInMillis = (long) mediaPlayer.getMedia().getDuration().toMillis();

                // pick out the total hours, minutes, seconds
                long durationSeconds = (int) durationInMillis / 1000;
                totalHours = (int) durationSeconds / 3600;
                durationSeconds -= totalHours * 3600;
                totalMinutes = (int) durationSeconds / 60;
                durationSeconds -= totalMinutes * 60;
                totalSeconds = (int) durationSeconds;
                updateProgress();
            }
        }

        /**
         * Responds to MediaPlayer onEndOfMediaEvents.
         *
         * Prepares the media to be replayed.
         */
        private class EndOfMediaListener implements Runnable {

            @Override
            public void run() {
                Duration beginning = mediaPlayer.getStartTime();
                mediaPlayer.stop();
                mediaPlayer.pause();
                pauseButton.setText(PLAY_TEXT);
                updateSlider(beginning);
                updateTime(beginning);
            }
        }

        /**
         * Responds to changes in the MediaPlayer currentTime property.
         *
         * Updates the progress slider and label with the current Time.
         */
        private class TimeListener implements ChangeListener<Duration> {

            @Override
            public void changed(ObservableValue<? extends Duration> observable, Duration oldValue, Duration newValue) {
                updateSlider(newValue);
                updateTime(newValue);
            }
        }

        /**
         * Triggered when MediaPlayer State changes to PAUSED or Stopped.
         */
        private class NotPlayListener implements Runnable {

            @Override
            public void run() {
                pauseButton.setText(PLAY_TEXT);
            }
        }

        /**
         * Triggered when MediaPlayer State changes to PLAYING.
         */
        private class PlayListener implements Runnable {

            @Override
            public void run() {
                pauseButton.setText(PAUSE_TEXT);
            }
        }
    }

    /**
     * @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<VideoFrame> captureFrames(java.io.File file, int numFrames) throws Exception {
//
//        try {
//        List<VideoFrame> frames = new ArrayList<>();
//
//        FrameCapturer fc = new FrameCapturer(file);
//        logger.log(Level.INFO, "Fc is null? " + (fc == null));
//        frames = fc.getFrames(numFrames);
//       
//        return frames;
//        }
//        catch (NullPointerException e) {
//            e.printStackTrace();
//            return null;
//        }
        return null;
    }

//    private class FrameCapturer {
//       
//        private MediaPlayer mediaPlayer;
//        private JFXPanel panel;
//        private boolean isReady = false;
//       
//        FrameCapturer(java.io.File file) {
//            initFx(file);
//        }
//       
//        boolean isReady() {
//            return isReady;
//        }
//       
//        private void initFx(final java.io.File file) {
//            Platform.runAndWait(new Runnable() {
//                @Override
//                public void run() {
//                    logger.log(Level.INFO, "In initFX.");
//                    // Create Media Player with no video output
//                    Media media = new Media(Paths.get(file.getAbsolutePath()).toUri().toString());
//                    mediaPlayer = new MediaPlayer(media);
//                    MediaView mediaView = new MediaView(mediaPlayer);
//                    mediaView.setStyle("-fx-background-color: black");
//                    Pane mediaViewPane = new Pane();
//                    mediaViewPane.getChildren().add(mediaView);
//                    Scene scene = new Scene(mediaViewPane);
//                    panel = new JFXPanel();
//                    panel.setScene(scene);
//                    isReady = true;
//                }
//            });
//        }
//       
//        List<VideoFrame> getFrames(int numFrames) {
//            logger.log(Level.INFO, "in get frames");
//            List<VideoFrame> frames = new ArrayList<VideoFrame>(0);
//           
//            if (mediaPlayer.getStatus() != Status.READY) {
//                try {
//                   Thread.sleep(500);
//               } catch (InterruptedException e) {
//                   return frames;
//               }
//            }
//
//            // get the duration of the video
//            long myDurationMillis = (long) mediaPlayer.getMedia().getDuration().toMillis();
//            if (myDurationMillis <= 0) {
//               return frames;
//            }
//
//            // calculate the frame interval
//            int numFramesToGet = numFrames;
//            long frameInterval = (myDurationMillis - INTER_FRAME_PERIOD_MS) / numFrames;
//            if (frameInterval < MIN_FRAME_INTERVAL_MILLIS) {
//               numFramesToGet = 1;
//            }
//
//            final Object frameLock = new Object();
//            BufferedImage frame;
//            final int width = (int) panel.getSize().getWidth();
//            final int height = (int) panel.getSize().getHeight();
//            // for each timeStamp, grap a frame
//            for (int i = 0; i < numFramesToGet; ++i) {
//               frame = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
//               logger.log(Level.INFO, "Grabbing a frame...");
//               final long timeStamp = i * frameInterval + INTER_FRAME_PERIOD_MS;
//
//            //            Platform.runLater(new Runnable() {
//            //                @Override
//            //                public void run() {
//            //                    synchronized (frameLock) {
//                           logger.log(Level.INFO, "seeking.");
//                           mediaPlayer.seek(new Duration(timeStamp));
//            //                    }
//            //                }
//            //            });
//
//               synchronized (frameLock) {
//                   panel.paint(frame.createGraphics());
//                   logger.log(Level.INFO, "Adding image to frames");
//               }
//               frames.add(new VideoFrame(frame, timeStamp));
//            }
//            return frames;
//        }
//    }
    @Override
    public String[] getExtensions() {
        return EXTENSIONS;
    }

    @Override
    public List<String> getMimeTypes() {
        return MIMETYPES;
    }
}
TOP

Related Classes of org.sleuthkit.autopsy.corecomponents.FXVideoPanel$MediaPane$TimeListener

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.