Beispiel #1
0
    /**
     * As long as the processing thread is active, this executes detection on frames continuously.
     * The next pending frame is either immediately available or hasn't been received yet. Once it
     * is available, we transfer the frame info to local variables and run detection on that frame.
     * It immediately loops back for the next frame without pausing.
     *
     * <p>If detection takes longer than the time in between new frames from the camera, this will
     * mean that this loop will run without ever waiting on a frame, avoiding any context switching
     * or frame acquisition time latency.
     *
     * <p>If you find that this is using more CPU than you'd like, you should probably decrease the
     * FPS setting above to allow for some idle time in between frames.
     */
    @Override
    public void run() {
      Frame outputFrame;
      ByteBuffer data;

      while (true) {
        synchronized (mLock) {
          if (mActive && (mPendingFrameData == null)) {
            try {
              // Wait for the next frame to be received from the camera, since we
              // don't have it yet.
              mLock.wait();
            } catch (InterruptedException e) {
              Log.d(TAG, mContext.getString(R.string.frame_processing_loop_terminated), e);
              return;
            }
          }

          if (!mActive) {
            // Exit the loop once this camera source is stopped or released.  We check
            // this here, immediately after the wait() above, to handle the case where
            // setActive(false) had been called, triggering the termination of this
            // loop.
            return;
          }

          outputFrame =
              new Frame.Builder()
                  .setImageData(
                      mPendingFrameData,
                      mPreviewSize.getWidth(),
                      mPreviewSize.getHeight(),
                      ImageFormat.NV21)
                  .setId(mPendingFrameId)
                  .setTimestampMillis(mPendingTimeMillis)
                  .setRotation(mRotation)
                  .build();

          // Hold onto the frame data locally, so that we can use this for detection
          // below.  We need to clear mPendingFrameData to ensure that this buffer isn't
          // recycled back to the camera before we are done using that data.
          data = mPendingFrameData;
          mPendingFrameData = null;
        }

        // The code below needs to run outside of synchronization, because this will allow
        // the camera to add pending frame(s) while we are running detection on the current
        // frame.

        try {
          mDetector.receiveFrame(outputFrame);
        } catch (Throwable t) {
          Log.e(TAG, mContext.getString(R.string.exception_from_receiver), t);
        } finally {
          mCamera.addCallbackBuffer(data.array());
        }
      }
    }
Beispiel #2
0
 /**
  * Releases the underlying receiver. This is only safe to do after the associated thread has
  * completed, which is managed in camera source's release method above.
  */
 @SuppressLint("Assert")
 void release() {
   assert (mProcessingThread.getState() == State.TERMINATED);
   mDetector.release();
   mDetector = null;
 }