Home | History | Annotate | Download | only in simplecamera
      1 /*
      2  * Copyright 2013 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 
     17 package androidx.media.filterfw.samples.simplecamera;
     18 
     19 import android.content.Context;
     20 import android.graphics.Bitmap;
     21 import android.graphics.ImageFormat;
     22 import android.hardware.camera2.CameraAccessException;
     23 import android.hardware.camera2.CameraCharacteristics;
     24 import android.hardware.camera2.CameraDevice;
     25 import android.hardware.camera2.CameraCaptureSession;
     26 import android.hardware.camera2.CameraManager;
     27 import android.hardware.camera2.CaptureFailure;
     28 import android.hardware.camera2.CaptureRequest;
     29 import android.hardware.camera2.CaptureResult;
     30 import android.hardware.camera2.TotalCaptureResult;
     31 import android.os.Handler;
     32 import android.renderscript.Allocation;
     33 import android.renderscript.Element;
     34 import android.renderscript.RenderScript;
     35 import android.renderscript.ScriptIntrinsicYuvToRGB;
     36 import android.renderscript.Type;
     37 import android.util.Log;
     38 import android.view.Surface;
     39 import com.android.ex.camera2.blocking.BlockingCameraManager;
     40 import com.android.ex.camera2.blocking.BlockingCameraManager.BlockingOpenException;
     41 import com.android.ex.camera2.blocking.BlockingSessionCallback;
     42 import androidx.media.filterfw.Filter;
     43 import androidx.media.filterfw.Frame;
     44 import androidx.media.filterfw.FrameImage2D;
     45 import androidx.media.filterfw.FrameType;
     46 import androidx.media.filterfw.FrameValue;
     47 import androidx.media.filterfw.MffContext;
     48 import androidx.media.filterfw.OutputPort;
     49 import androidx.media.filterfw.Signature;
     50 
     51 import java.util.ArrayList;
     52 import java.util.List;
     53 
     54 public class Camera2Source extends Filter implements Allocation.OnBufferAvailableListener {
     55 
     56     private boolean mNewFrameAvailable = false;
     57     private FrameType mOutputType;
     58     private static final String TAG = "Camera2Source";
     59     private CameraManager mCameraManager;
     60     private CameraDevice mCamera;
     61     private CameraCaptureSession mCameraSession;
     62     private RenderScript mRS;
     63     private Surface mSurface;
     64     private CameraCharacteristics mProperties;
     65     private CameraTestThread mLooperThread;
     66     private int mHeight = 480;
     67     private int mWidth = 640;
     68     private Allocation mAllocationIn;
     69     private ScriptIntrinsicYuvToRGB rgbConverter;
     70     private Allocation mAllocationOut;
     71     private Bitmap mBitmap;
     72 
     73     private static final long SESSION_TIMEOUT_MS = 2000;
     74 
     75     class MyCameraListener extends CameraManager.AvailabilityCallback {
     76 
     77         @Override
     78         public void onCameraAvailable(String cameraId) {
     79             // TODO Auto-generated method stub
     80             Log.v(TAG, "camera available to open");
     81         }
     82 
     83         @Override
     84         public void onCameraUnavailable(String cameraId) {
     85             // TODO Auto-generated method stub
     86             Log.v(TAG, "camera unavailable to open");
     87         }
     88 
     89     }
     90 
     91     class MyCaptureCallback extends CameraCaptureSession.CaptureCallback {
     92 
     93         @Override
     94         public void onCaptureCompleted(CameraCaptureSession camera, CaptureRequest request,
     95                 TotalCaptureResult result) {
     96             // TODO Auto-generated method stub
     97             Log.v(TAG, "in onCaptureComplete");
     98 
     99         }
    100 
    101         @Override
    102         public void onCaptureFailed(CameraCaptureSession camera, CaptureRequest request,
    103                 CaptureFailure failure) {
    104             // TODO Auto-generated method stub
    105             Log.v(TAG, "onCaptureFailed is being called");
    106         }
    107 
    108     }
    109 
    110     public Camera2Source(MffContext context, String name) {
    111         super(context, name);
    112         mOutputType = FrameType.image2D(FrameType.ELEMENT_RGBA8888, FrameType.WRITE_GPU);
    113 
    114         Context ctx = context.getApplicationContext();
    115         mCameraManager = (CameraManager) ctx.getSystemService(Context.CAMERA_SERVICE);
    116 
    117         mRS = RenderScript.create(context.getApplicationContext());
    118     }
    119 
    120     @Override
    121     public Signature getSignature() {
    122         return new Signature()
    123                 .addOutputPort("timestamp", Signature.PORT_OPTIONAL, FrameType.single(long.class))
    124                 .addOutputPort("video", Signature.PORT_REQUIRED, mOutputType)
    125                 .addOutputPort("orientation", Signature.PORT_REQUIRED,
    126                         FrameType.single(float.class))
    127                 .disallowOtherPorts();
    128     }
    129 
    130     @Override
    131     protected void onClose() {
    132         Log.v(TAG, "onClose being called");
    133         try {
    134             mCamera.close();
    135             mSurface.release();
    136             mLooperThread.close();
    137         } catch (Exception e) {
    138             // TODO Auto-generated catch block
    139             e.printStackTrace();
    140         }
    141     }
    142 
    143     @Override
    144     protected void onOpen() {
    145         mLooperThread = new CameraTestThread();
    146         Handler mHandler;
    147         try {
    148             mHandler = mLooperThread.start();
    149         } catch (Exception e) {
    150             // TODO Auto-generated catch block
    151             e.printStackTrace();
    152             throw new RuntimeException(e);
    153         }
    154 
    155         try {
    156             String backCameraId = "0";
    157             BlockingCameraManager blkManager = new BlockingCameraManager(mCameraManager);
    158             mCamera = blkManager.openCamera(backCameraId, /*listener*/null, mHandler);
    159         } catch (CameraAccessException e) {
    160             e.printStackTrace();
    161             throw new RuntimeException(e);
    162         } catch (BlockingOpenException e) {
    163             e.printStackTrace();
    164             throw new RuntimeException(e);
    165         }
    166 
    167         Element ele = Element.createPixel(mRS, Element.DataType.UNSIGNED_8,
    168                 Element.DataKind.PIXEL_YUV);
    169 
    170         rgbConverter = ScriptIntrinsicYuvToRGB.create(mRS,ele);
    171         Type.Builder yuvBuilder = new Type.Builder(mRS,ele);
    172 
    173         yuvBuilder.setYuvFormat(ImageFormat.YUV_420_888);
    174         yuvBuilder.setX(mWidth);
    175         yuvBuilder.setY(mHeight);
    176         mAllocationIn = Allocation.createTyped(mRS, yuvBuilder.create(),
    177                 Allocation.USAGE_SCRIPT | Allocation.USAGE_IO_INPUT);
    178         mSurface = mAllocationIn.getSurface();
    179         mAllocationIn.setOnBufferAvailableListener(this);
    180         rgbConverter.setInput(mAllocationIn);
    181 
    182         mBitmap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);
    183         mAllocationOut = Allocation.createFromBitmap(mRS, mBitmap);
    184 
    185 
    186         Log.v(TAG, "mcamera: " + mCamera);
    187 
    188         List<Surface> surfaces = new ArrayList<Surface>();
    189         surfaces.add(mSurface);
    190         CaptureRequest.Builder mCaptureRequest = null;
    191         try {
    192             BlockingSessionCallback blkSession = new BlockingSessionCallback();
    193 
    194             mCamera.createCaptureSession(surfaces, blkSession, mHandler);
    195             mCaptureRequest = mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
    196             mCaptureRequest.addTarget(mSurface);
    197 
    198             mCameraSession = blkSession.waitAndGetSession(SESSION_TIMEOUT_MS);
    199 
    200         } catch (CameraAccessException e) {
    201             e.printStackTrace();
    202             throw new RuntimeException(e);
    203         }
    204 
    205         try {
    206             mCameraSession.setRepeatingRequest(mCaptureRequest.build(), new MyCaptureCallback(),
    207                     mHandler);
    208         } catch (CameraAccessException e) {
    209             e.printStackTrace();
    210             throw new RuntimeException(e);
    211         }
    212         mProperties = null;
    213         try {
    214             mProperties = mCameraManager.getCameraCharacteristics(mCamera.getId());
    215         } catch (CameraAccessException e) {
    216             e.printStackTrace();
    217             throw new RuntimeException(e);
    218         }
    219 
    220     }
    221 
    222     @Override
    223     protected void onProcess() {
    224         Log.v(TAG, "on Process");
    225         if (nextFrame()) {
    226             OutputPort outPort = getConnectedOutputPort("video");
    227 
    228             // Create a 2D frame that will hold the output
    229             int[] dims = new int[] {
    230                     mWidth, mHeight
    231             };
    232             FrameImage2D outputFrame = Frame.create(mOutputType, dims).asFrameImage2D();
    233             rgbConverter.forEach(mAllocationOut);
    234             mAllocationOut.copyTo(mBitmap);
    235             outputFrame.setBitmap(mBitmap);
    236             outPort.pushFrame(outputFrame);
    237             outputFrame.release();
    238 
    239             OutputPort orientationPort = getConnectedOutputPort("orientation");
    240             FrameValue orientationFrame = orientationPort.fetchAvailableFrame(null).asFrameValue();
    241 
    242             // FIXME: Hardcoded value because ORIENTATION returns null, Qualcomm
    243             // bug
    244             Integer orientation = mProperties.get(CameraCharacteristics.SENSOR_ORIENTATION);
    245             float temp;
    246             if (orientation != null) {
    247                 temp = orientation.floatValue();
    248             } else {
    249                 temp = 90.0f;
    250             }
    251             orientationFrame.setValue(temp);
    252             orientationPort.pushFrame(orientationFrame);
    253         }
    254     }
    255 
    256     private synchronized boolean nextFrame() {
    257         boolean frameAvailable = mNewFrameAvailable;
    258         if (frameAvailable) {
    259             mNewFrameAvailable = false;
    260         } else {
    261             enterSleepState();
    262         }
    263         return frameAvailable;
    264     }
    265 
    266     public void onBufferAvailable(Allocation a) {
    267         Log.v(TAG, "on Buffer Available");
    268         a.ioReceive();
    269         synchronized (this) {
    270             mNewFrameAvailable = true;
    271         }
    272         wakeUp();
    273     }
    274 
    275 
    276 }
    277