/* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.example.rscamera; import android.graphics.ImageFormat; import android.os.Handler; import android.os.HandlerThread; import android.renderscript.Allocation; import android.renderscript.Element; import android.renderscript.RenderScript; import android.renderscript.Type; import android.util.Size; import android.view.Surface; /** * Renderscript-based Focus peaking viewfinder */ public class ViewfinderProcessor { int mCount; long mLastTime; float mFps; private Allocation mInputAllocation; private Allocation mOutputAllocation; private HandlerThread mProcessingThread; private Handler mProcessingHandler; private ScriptC_focus_peak mScriptFocusPeak; public ProcessingTask mProcessingTask; public ViewfinderProcessor(RenderScript rs, Size dimensions) { Type.Builder yuvTypeBuilder = new Type.Builder(rs, Element.YUV(rs)); yuvTypeBuilder.setX(dimensions.getWidth()); yuvTypeBuilder.setY(dimensions.getHeight()); yuvTypeBuilder.setYuvFormat(ImageFormat.YUV_420_888); mInputAllocation = Allocation.createTyped(rs, yuvTypeBuilder.create(), Allocation.USAGE_IO_INPUT | Allocation.USAGE_SCRIPT); Type.Builder rgbTypeBuilder = new Type.Builder(rs, Element.RGBA_8888(rs)); rgbTypeBuilder.setX(dimensions.getWidth()); rgbTypeBuilder.setY(dimensions.getHeight()); mOutputAllocation = Allocation.createTyped(rs, rgbTypeBuilder.create(), Allocation.USAGE_IO_OUTPUT | Allocation.USAGE_SCRIPT); mProcessingThread = new HandlerThread("ViewfinderProcessor"); mProcessingThread.start(); mProcessingHandler = new Handler(mProcessingThread.getLooper()); mScriptFocusPeak = new ScriptC_focus_peak(rs); mProcessingTask = new ProcessingTask(mInputAllocation); } public Surface getInputSurface() { return mInputAllocation.getSurface(); } public void setOutputSurface(Surface output) { mOutputAllocation.setSurface(output); } public float getmFps() { return mFps; } /** * Class to process buffer from camera and output to buffer to screen */ class ProcessingTask implements Runnable, Allocation.OnBufferAvailableListener { private int mPendingFrames = 0; private Allocation mInputAllocation; public ProcessingTask(Allocation input) { mInputAllocation = input; mInputAllocation.setOnBufferAvailableListener(this); } @Override public void onBufferAvailable(Allocation a) { synchronized (this) { mPendingFrames++; mProcessingHandler.post(this); } } @Override public void run() { // Find out how many frames have arrived int pendingFrames; synchronized (this) { pendingFrames = mPendingFrames; mPendingFrames = 0; // Discard extra messages in case processing is slower than frame rate mProcessingHandler.removeCallbacks(this); } // Get to newest input for (int i = 0; i < pendingFrames; i++) { mInputAllocation.ioReceive(); } mCount++; mScriptFocusPeak.set_gCurrentFrame(mInputAllocation); long time = System.currentTimeMillis() - mLastTime; if (time > 1000) { mLastTime += time; mFps = mCount * 1000 / (float) (time); mCount = 0; } // Run processing pass mScriptFocusPeak.forEach_peak(mOutputAllocation); mOutputAllocation.ioSend(); } } }