Reputation: 893
I have a java class which in fact capture frames from a webcamer. This class has two methods one for start and one for stop. I want to add this class to a gui that I have create. However when I add the functions as they are my game is stuck. It seems that I need to do some multithread here. How can I add my class methods into new threads?
EDIT: My code right now is the following:
Thread t2 = new Thread(new Runnable() {
public void run()
{
VideoCapture videoCapture = VideoCapture.create(VideoFormat.WMV);
List<VideoSource> availableVideoSources = VideoSource.getAvailable();
//System.out.println("availableVideoSources = " + availableVideoSources);
if (availableVideoSources.isEmpty()) {
throw new IllegalStateException("No external video sources available");
}
VideoSource webCamera = availableVideoSources.get(0);
//System.out.println("webCamera = " + webCamera);
videoCapture.setVideoSource(webCamera);
java.util.List<Codec> videoCodecs = videoCapture.getVideoCodecs();
//System.out.println("videoCodecs = " + videoCodecs);
if (videoCodecs.isEmpty()) {
throw new IllegalStateException("No video codecs available");
}
Codec videoCodec = videoCodecs.get(2);
//System.out.println("videoCodec = " + videoCodec);
EncodingParameters encodingParameters = new EncodingParameters(new File("file.wmv"));
encodingParameters.setBitrate(500000);
encodingParameters.setFramerate(10);
encodingParameters.setKeyFrameInterval(1);
encodingParameters.setCodec(videoCodec);
videoCapture.setEncodingParameters(encodingParameters);
videoCapture.start();
//System.in.read();
//videoCapture.stop();
}});
I am running this thread by calling t2.start() how can I call videoCapture.stop() in a second function??
Upvotes: 1
Views: 66
Reputation: 1145
Use an AtomicBoolean to represent state between your two methods, and use the state to read or terminate the stream.
import java.util.concurrent.atomic.AtomicBoolean;
public class CameraCapture {
private AtomicBoolean doCapture = new AtomicBoolean();
public Thread startCapture() {
System.out.println("Setting Capture status to true");
doCapture.set(true);
Thread capture = new Thread(new Runnable() {
public void run() {
System.out.println("Initializing Sources");
/* Initialization Code here. */
System.out.println("Found WebCam!");
System.out.println("Configuring Codec");
while(doCapture.get()) {
System.out.println("\tReading Data!");
//Read and handle input.
try {
Thread.sleep(1000);
} catch (InterruptedException exception) {
// FIXME: minimum of logging.
exception.printStackTrace();
}
}
System.out.println("Capture Terminated!");
}}, "CameraCapture Injest"); //Name the thread!
System.out.println("Starting Capture");
capture.start();
return capture;
}
public void stopCapture() {
System.out.println("Disabling capture");
doCapture.set(false);
}
}
This test should show the workflow in the console.
@Test
public void captureThreadTest() throws Exception {
CameraCapture capture = new CameraCapture();
Thread captureRunner = capture.startCapture();
Thread.sleep(10000);
capture.stopCapture();
captureRunner.join();
}
Note that I'm returning the Thread reference from startCapture soley for the purpose of the unit test example (since I needed to perform the join() to get the last output). I wouldn't recommend exposing that in production code, as that does not provide good encapsulation and ownership for the state of that Thread.
Setting Capture status to true
Starting Capture
Initializing Sources
Found WebCam!
Configuring Codec
Reading Data!
Reading Data!
Reading Data!
Reading Data!
Reading Data!
Reading Data!
Reading Data!
Reading Data!
Reading Data!
Reading Data!
Disabling capture
Capture Terminated!
Upvotes: 1
Reputation: 5331
Runner
. If you are using Eclipse, there is a template which will automatically write your runner for you. Also, if you are using Swing, you should address everything to the Swing event queue.
If you have not done so already, you may need to redesign the GUI so that it is a controller instead of the application itself (well, presumably, from the fact that you're having this threading issue with the GUI).
Relevant Docs
Runnable
docs: https://docs.oracle.com/javase/7/docs/api/java/lang/Runnable.html
EventQueue.invokeLater(Runnable)
docs: http://docs.oracle.com/javase/8/docs/api/java/awt/EventQueue.html#invokeLater-java.lang.Runnable-
Concurrency and SwingWorker
: https://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html
Upvotes: 2