Autopsy  4.10.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
GstVideoRendererPanel.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2019 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.autopsy.contentviewers;
20 
21 import java.nio.ByteBuffer;
22 import java.nio.ByteOrder;
23 import javafx.application.Platform;
24 import javafx.embed.swing.JFXPanel;
25 import javafx.scene.Scene;
26 import javafx.scene.image.Image;
27 import javafx.scene.image.ImageView;
28 import javafx.scene.image.PixelFormat;
29 import javafx.scene.image.PixelWriter;
30 import javafx.scene.image.WritableImage;
31 import javafx.scene.layout.BorderPane;
32 import org.freedesktop.gstreamer.Buffer;
33 import org.freedesktop.gstreamer.Caps;
34 import org.freedesktop.gstreamer.FlowReturn;
35 import org.freedesktop.gstreamer.Sample;
36 import org.freedesktop.gstreamer.Structure;
37 import org.freedesktop.gstreamer.elements.AppSink;
38 
42 final class GstVideoRendererPanel extends JFXPanel {
43 
44  private static final String CAP_MIME_TYPE = "video/x-raw";
45  private static final String CAP_BYTE_ORDER = (ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN ? "format=BGRx" : "format=xRGB");
46  private static final int PROP_MAX_BUFFERS = 5000;
47  private AppSink videoSink;
48  private ImageView fxImageView;
49 
53  GstVideoRendererPanel() {
54  initImageView();
55  initVideoSink();
56  }
57 
61  private void initImageView() {
62  fxImageView = new ImageView(); // Will hold the current video frame.
63  BorderPane borderpane = new BorderPane(fxImageView); // Center and size ImageView.
64  Scene scene = new Scene(borderpane); // Root of the JavaFX tree.
65  setScene(scene);
66 
67  // Bind size of image to that of scene, while keeping proportions
68  fxImageView.fitWidthProperty().bind(scene.widthProperty());
69  fxImageView.fitHeightProperty().bind(scene.heightProperty());
70  fxImageView.setPreserveRatio(true);
71  fxImageView.setSmooth(true);
72  fxImageView.setCache(true);
73  }
74 
78  private void initVideoSink() {
79  videoSink = new AppSink("GstVideoComponent");
80  videoSink.set("emit-signals", true);
81  AppSinkListener gstListener = new AppSinkListener();
82  videoSink.connect(gstListener);
83  videoSink.setCaps(new Caps(
84  String.format("%s, %s", CAP_MIME_TYPE, CAP_BYTE_ORDER)));
85  videoSink.set("max-buffers", PROP_MAX_BUFFERS);
86  videoSink.set("drop", true);
87  }
88 
94  AppSink getVideoSink() {
95  return videoSink;
96  }
97 
102  class AppSinkListener implements AppSink.NEW_SAMPLE {
103 
104  private Image videoFrame;
105  private int lastWidth = 0;
106  private int lastHeight = 0;
107  private byte[] byteArray;
108 
109  @Override
110  public FlowReturn newSample(AppSink appSink) {
111  Sample sample = appSink.pullSample();
112  Buffer buffer = sample.getBuffer();
113  ByteBuffer byteBuffer = buffer.map(false);
114  if (byteBuffer != null) {
115  Structure capsStruct = sample.getCaps().getStructure(0);
116  int width = capsStruct.getInteger("width");
117  int height = capsStruct.getInteger("height");
118  if (width != lastWidth || height != lastHeight) {
119  lastWidth = width;
120  lastHeight = height;
121  byteArray = new byte[width * height * 4];
122  }
123  byteBuffer.get(byteArray);
124  videoFrame = convertBytesToImage(byteArray, width, height);
125  Platform.runLater(() -> {
126  fxImageView.setImage(videoFrame);
127  });
128  buffer.unmap();
129  }
130  sample.dispose();
131 
132  return FlowReturn.OK;
133  }
134 
144  private Image convertBytesToImage(byte[] pixels, int width, int height) {
145  WritableImage image = new WritableImage(width, height);
146  PixelWriter pixelWriter = image.getPixelWriter();
147  pixelWriter.setPixels(0, 0, width, height, PixelFormat.getByteBgraInstance(), pixels, 0, width * 4);
148  return image;
149  }
150  }
151 }

Copyright © 2012-2018 Basis Technology. Generated on: Fri Mar 22 2019
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.