1/* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.example.rscamera; 18 19import android.graphics.ImageFormat; 20import android.os.Handler; 21import android.os.HandlerThread; 22import android.renderscript.Allocation; 23import android.renderscript.Element; 24import android.renderscript.RenderScript; 25import android.renderscript.Type; 26import android.util.Size; 27import android.view.Surface; 28 29/** 30 * Renderscript-based Focus peaking viewfinder 31 */ 32public class ViewfinderProcessor { 33 int mCount; 34 long mLastTime; 35 float mFps; 36 private Allocation mInputAllocation; 37 private Allocation mOutputAllocation; 38 private HandlerThread mProcessingThread; 39 private Handler mProcessingHandler; 40 private ScriptC_focus_peak mScriptFocusPeak; 41 public ProcessingTask mProcessingTask; 42 43 public ViewfinderProcessor(RenderScript rs, Size dimensions) { 44 Type.Builder yuvTypeBuilder = new Type.Builder(rs, Element.YUV(rs)); 45 yuvTypeBuilder.setX(dimensions.getWidth()); 46 yuvTypeBuilder.setY(dimensions.getHeight()); 47 yuvTypeBuilder.setYuvFormat(ImageFormat.YUV_420_888); 48 49 mInputAllocation = Allocation.createTyped(rs, yuvTypeBuilder.create(), 50 Allocation.USAGE_IO_INPUT | Allocation.USAGE_SCRIPT); 51 52 Type.Builder rgbTypeBuilder = new Type.Builder(rs, Element.RGBA_8888(rs)); 53 rgbTypeBuilder.setX(dimensions.getWidth()); 54 rgbTypeBuilder.setY(dimensions.getHeight()); 55 56 mOutputAllocation = Allocation.createTyped(rs, rgbTypeBuilder.create(), 57 Allocation.USAGE_IO_OUTPUT | Allocation.USAGE_SCRIPT); 58 59 mProcessingThread = new HandlerThread("ViewfinderProcessor"); 60 mProcessingThread.start(); 61 mProcessingHandler = new Handler(mProcessingThread.getLooper()); 62 mScriptFocusPeak = new ScriptC_focus_peak(rs); 63 mProcessingTask = new ProcessingTask(mInputAllocation); 64 } 65 66 public Surface getInputSurface() { 67 return mInputAllocation.getSurface(); 68 } 69 70 public void setOutputSurface(Surface output) { 71 mOutputAllocation.setSurface(output); 72 } 73 74 public float getmFps() { 75 return mFps; 76 } 77 78 /** 79 * Class to process buffer from camera and output to buffer to screen 80 */ 81 class ProcessingTask implements Runnable, Allocation.OnBufferAvailableListener { 82 private int mPendingFrames = 0; 83 84 private Allocation mInputAllocation; 85 86 public ProcessingTask(Allocation input) { 87 mInputAllocation = input; 88 mInputAllocation.setOnBufferAvailableListener(this); 89 } 90 91 @Override 92 public void onBufferAvailable(Allocation a) { 93 synchronized (this) { 94 mPendingFrames++; 95 mProcessingHandler.post(this); 96 } 97 } 98 99 @Override 100 public void run() { 101 // Find out how many frames have arrived 102 int pendingFrames; 103 synchronized (this) { 104 pendingFrames = mPendingFrames; 105 mPendingFrames = 0; 106 107 // Discard extra messages in case processing is slower than frame rate 108 mProcessingHandler.removeCallbacks(this); 109 } 110 111 // Get to newest input 112 for (int i = 0; i < pendingFrames; i++) { 113 mInputAllocation.ioReceive(); 114 } 115 mCount++; 116 mScriptFocusPeak.set_gCurrentFrame(mInputAllocation); 117 long time = System.currentTimeMillis() - mLastTime; 118 if (time > 1000) { 119 mLastTime += time; 120 mFps = mCount * 1000 / (float) (time); 121 mCount = 0; 122 } 123 // Run processing pass 124 mScriptFocusPeak.forEach_peak(mOutputAllocation); 125 mOutputAllocation.ioSend(); 126 } 127 } 128}