|
|
@ -18,7 +18,7 @@ a QR code detector, the |
|
|
|
cameraView.addFrameProcessor(new FrameProcessor() { |
|
|
|
cameraView.addFrameProcessor(new FrameProcessor() { |
|
|
|
@Override |
|
|
|
@Override |
|
|
|
@WorkerThread |
|
|
|
@WorkerThread |
|
|
|
public void process(Frame frame) { |
|
|
|
public void process(@NonNull Frame frame) { |
|
|
|
byte[] data = frame.getData(); |
|
|
|
byte[] data = frame.getData(); |
|
|
|
int rotation = frame.getRotation(); |
|
|
|
int rotation = frame.getRotation(); |
|
|
|
long time = frame.getTime(); |
|
|
|
long time = frame.getTime(); |
|
|
@ -33,9 +33,45 @@ For your convenience, the `FrameProcessor` method is run in a background thread |
|
|
|
in a synchronous fashion. Once the process method returns, internally we will re-use the `Frame` instance and |
|
|
|
in a synchronous fashion. Once the process method returns, internally we will re-use the `Frame` instance and |
|
|
|
apply new data to it. So: |
|
|
|
apply new data to it. So: |
|
|
|
|
|
|
|
|
|
|
|
- you can do your job synchronously in the `process()` method |
|
|
|
- you can do your job synchronously in the `process()` method. This is **recommended**. |
|
|
|
- if you must hold the `Frame` instance longer, use `frame = frame.freeze()` to get a frozen instance |
|
|
|
- if you must hold the `Frame` instance longer, use `frame = frame.freeze()` to get a frozen instance |
|
|
|
that will not be affected |
|
|
|
that will not be affected. This is **discouraged** because it requires copying the whole array. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### Process synchronously |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Processing synchronously, for the duration of the `process()` method, is the recommended way of using |
|
|
|
|
|
|
|
processors, because it solves different issues: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- avoids the need of calling `frame = frame.freeze()` which is a very expensive operation |
|
|
|
|
|
|
|
- the engine will **automatically drop frames** if the `process()` method is busy, so you'll only receive frames that you can handle |
|
|
|
|
|
|
|
- we have already allocated a thread for you, so there's no need to create another |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Some frame consumers might have a built-in asynchronous behavior. |
|
|
|
|
|
|
|
But you can still block the `process()` thread until the consumer has returned. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```java |
|
|
|
|
|
|
|
@Override |
|
|
|
|
|
|
|
@WorkerThread |
|
|
|
|
|
|
|
public void process(@NonNull Frame frame) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// EXAMPLE 1: |
|
|
|
|
|
|
|
// Firebase and Google APIs will often return a Task. |
|
|
|
|
|
|
|
// You can use Tasks.await() to complete the task on the current thread. |
|
|
|
|
|
|
|
Tasks.await(firebaseDetector.detectInImage(firebaseImage)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// EXAMPLE 2: |
|
|
|
|
|
|
|
// For other async consumers, you can use, for example, a CountDownLatch. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Step 1: create the latch. |
|
|
|
|
|
|
|
final CountDownLatch latch = new CountDownLatch(1); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Step 2: launch async processing here... |
|
|
|
|
|
|
|
// When processing completes or fails, call latch.countDown(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Step 3: after launching, block the current thread. |
|
|
|
|
|
|
|
latch.await(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
``` |
|
|
|
|
|
|
|
|
|
|
|
### Related APIs |
|
|
|
### Related APIs |
|
|
|
|
|
|
|
|
|
|
|