/*
- * Copyright 2007 Google Inc.
+ * Copyright 2007 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
import javax.microedition.media.control.VideoControl;
/**
- * @author Sean Owen (srowen@google.com)
+ * Thread which does the work of capturing a frame and decoding it.
+ *
+ * @author Sean Owen
*/
-final class SnapshotThread extends Thread {
-
- private static SnapshotThread currentThread;
+final class SnapshotThread implements Runnable {
private final ZXingMIDlet zXingMIDlet;
+ private final Object waitLock;
+ private volatile boolean done;
+ private final MultimediaManager multimediaManager;
+ private String bestEncoding;
SnapshotThread(ZXingMIDlet zXingMIDlet) {
this.zXingMIDlet = zXingMIDlet;
+ waitLock = new Object();
+ done = false;
+ multimediaManager = ZXingMIDlet.buildMultimediaManager();
+ }
+
+ void continueRun() {
+ synchronized (waitLock) {
+ waitLock.notifyAll();
+ }
}
- static synchronized void startThread(ZXingMIDlet zXingMIDlet) {
- if (currentThread == null) {
- currentThread = new SnapshotThread(zXingMIDlet);
- currentThread.start();
+ private void waitForSignal() {
+ synchronized (waitLock) {
+ try {
+ waitLock.wait();
+ } catch (InterruptedException ie) {
+ // continue
+ }
}
}
+ void stop() {
+ done = true;
+ continueRun();
+ }
+
public void run() {
Player player = zXingMIDlet.getPlayer();
+ do {
+ waitForSignal();
+ try {
+ multimediaManager.setFocus(player);
+ byte[] snapshot = takeSnapshot();
+ Image capturedImage = Image.createImage(snapshot, 0, snapshot.length);
+ MonochromeBitmapSource source = new LCDUIImageMonochromeBitmapSource(capturedImage);
+ Reader reader = new MultiFormatReader();
+ Result result = reader.decode(source);
+ zXingMIDlet.handleDecodedText(result);
+ } catch (ReaderException re) {
+ // Show a friendlier message on a mere failure to read the barcode
+ zXingMIDlet.showError("Sorry, no barcode was found.");
+ } catch (MediaException me) {
+ zXingMIDlet.showError(me);
+ } catch (RuntimeException re) {
+ zXingMIDlet.showError(re);
+ }
+ } while (!done);
+ }
+
+ private byte[] takeSnapshot() throws MediaException {
+
+ String bestEncoding = guessBestEncoding();
+
+ VideoControl videoControl = zXingMIDlet.getVideoControl();
+ byte[] snapshot = null;
try {
- AdvancedMultimediaManager.setFocus(player);
- try {
- player.stop();
- } catch (MediaException me) {
- // continue
- }
- byte[] snapshot = takeSnapshot();
- Image capturedImage = Image.createImage(snapshot, 0, snapshot.length);
- MonochromeBitmapSource source = new LCDUIImageMonochromeBitmapSource(capturedImage);
- Reader reader = new MultiFormatReader();
- Result result = reader.decode(source);
- zXingMIDlet.handleDecodedText(result.getText());
- } catch (ReaderException re) {
- // Show a friendlier message on a mere failure to read the barcode
- zXingMIDlet.showError("No barcode was detected in this image. Try again.");
- } catch (Throwable t) {
- zXingMIDlet.showError(t);
- } finally {
- try {
- player.start();
- } catch (MediaException me) {
- // continue
- }
- currentThread = null;
+ snapshot = videoControl.getSnapshot("".equals(bestEncoding) ? null : bestEncoding);
+ } catch (MediaException me) {
}
-
+ if (snapshot == null) {
+ // Fall back on JPEG; seems that some cameras default to PNG even
+ // when PNG isn't supported!
+ snapshot = videoControl.getSnapshot("encoding=jpeg");
+ if (snapshot == null) {
+ throw new MediaException("Can't obtain a snapshot");
+ }
+ }
+ return snapshot;
}
- private byte[] takeSnapshot() throws MediaException {
- VideoControl videoControl = zXingMIDlet.getVideoControl();
- byte[] snapshot = null;
- try {
- snapshot = videoControl.getSnapshot(null);
- } catch (MediaException me) {
- }
- if (snapshot == null) {
- // Fall back on JPEG; seems that some cameras default to PNG even
- // when PNG isn't supported!
- snapshot = videoControl.getSnapshot("encoding=jpeg");
- if (snapshot == null) {
- throw new MediaException("Can't obtain a snapshot");
- }
- }
- return snapshot;
- }
+ private synchronized String guessBestEncoding() throws MediaException {
+ if (bestEncoding == null) {
+ // Check this property, present on some Nokias?
+ String supportsVideoCapture = System.getProperty("supports.video.capture");
+ if ("false".equals(supportsVideoCapture)) {
+ throw new MediaException("supports.video.capture is false");
+ }
+
+ bestEncoding = "";
+ String videoSnapshotEncodings = System.getProperty("video.snapshot.encodings");
+ if (videoSnapshotEncodings != null) {
+ // We know explicitly what the camera supports; see if PNG is among them since
+ // Image.createImage() should always support it
+ int pngEncodingStart = videoSnapshotEncodings.indexOf("encoding=png");
+ if (pngEncodingStart >= 0) {
+ int space = videoSnapshotEncodings.indexOf(' ', pngEncodingStart);
+ bestEncoding = space >= 0 ?
+ videoSnapshotEncodings.substring(pngEncodingStart, space) :
+ videoSnapshotEncodings.substring(pngEncodingStart);
+ }
+ }
+ }
+ return bestEncoding;
+ }
}