2 * Copyright 2013 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package androidx.media.filterfw.samples.simplecamera;
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.BlockingSessionListener;
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;
51 import java.util.ArrayList;
52 import java.util.List;
54 public class Camera2Source extends Filter implements Allocation.OnBufferAvailableListener {
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;
73 private static final long SESSION_TIMEOUT_MS = 2000;
75 class MyCameraListener extends CameraManager.AvailabilityListener {
78 public void onCameraAvailable(String cameraId) {
79 // TODO Auto-generated method stub
80 Log.v(TAG, "camera available to open");
84 public void onCameraUnavailable(String cameraId) {
85 // TODO Auto-generated method stub
86 Log.v(TAG, "camera unavailable to open");
91 class MyCaptureListener extends CameraCaptureSession.CaptureListener {
94 public void onCaptureCompleted(CameraCaptureSession camera, CaptureRequest request,
95 TotalCaptureResult result) {
96 // TODO Auto-generated method stub
97 Log.v(TAG, "in onCaptureComplete");
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");
110 public Camera2Source(MffContext context, String name) {
111 super(context, name);
112 mOutputType = FrameType.image2D(FrameType.ELEMENT_RGBA8888, FrameType.WRITE_GPU);
114 Context ctx = context.getApplicationContext();
115 mCameraManager = (CameraManager) ctx.getSystemService(Context.CAMERA_SERVICE);
117 mRS = RenderScript.create(context.getApplicationContext());
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();
131 protected void onClose() {
132 Log.v(TAG, "onClose being called");
136 mLooperThread.close();
137 } catch (Exception e) {
138 // TODO Auto-generated catch block
144 protected void onOpen() {
145 mLooperThread = new CameraTestThread();
148 mHandler = mLooperThread.start();
149 } catch (Exception e) {
150 // TODO Auto-generated catch block
152 throw new RuntimeException(e);
156 String backCameraId = "0";
157 BlockingCameraManager blkManager = new BlockingCameraManager(mCameraManager);
158 mCamera = blkManager.openCamera(backCameraId, /*listener*/null, mHandler);
159 } catch (CameraAccessException e) {
161 throw new RuntimeException(e);
162 } catch (BlockingOpenException e) {
164 throw new RuntimeException(e);
167 Element ele = Element.createPixel(mRS, Element.DataType.UNSIGNED_8,
168 Element.DataKind.PIXEL_YUV);
170 rgbConverter = ScriptIntrinsicYuvToRGB.create(mRS,ele);
171 Type.Builder yuvBuilder = new Type.Builder(mRS,ele);
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);
182 mBitmap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);
183 mAllocationOut = Allocation.createFromBitmap(mRS, mBitmap);
186 Log.v(TAG, "mcamera: " + mCamera);
188 List<Surface> surfaces = new ArrayList<Surface>();
189 surfaces.add(mSurface);
190 CaptureRequest.Builder mCaptureRequest = null;
192 BlockingSessionListener blkSession = new BlockingSessionListener();
194 mCamera.createCaptureSession(surfaces, blkSession, mHandler);
195 mCaptureRequest = mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
196 mCaptureRequest.addTarget(mSurface);
198 mCameraSession = blkSession.waitAndGetSession(SESSION_TIMEOUT_MS);
200 } catch (CameraAccessException e) {
202 throw new RuntimeException(e);
206 mCameraSession.setRepeatingRequest(mCaptureRequest.build(), new MyCaptureListener(),
208 } catch (CameraAccessException e) {
210 throw new RuntimeException(e);
214 mProperties = mCameraManager.getCameraCharacteristics(mCamera.getId());
215 } catch (CameraAccessException e) {
217 throw new RuntimeException(e);
223 protected void onProcess() {
224 Log.v(TAG, "on Process");
226 OutputPort outPort = getConnectedOutputPort("video");
228 // Create a 2D frame that will hold the output
229 int[] dims = new int[] {
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();
239 OutputPort orientationPort = getConnectedOutputPort("orientation");
240 FrameValue orientationFrame = orientationPort.fetchAvailableFrame(null).asFrameValue();
242 // FIXME: Hardcoded value because ORIENTATION returns null, Qualcomm
244 Integer orientation = mProperties.get(CameraCharacteristics.SENSOR_ORIENTATION);
246 if (orientation != null) {
247 temp = orientation.floatValue();
251 orientationFrame.setValue(temp);
252 orientationPort.pushFrame(orientationFrame);
256 private synchronized boolean nextFrame() {
257 boolean frameAvailable = mNewFrameAvailable;
258 if (frameAvailable) {
259 mNewFrameAvailable = false;
263 return frameAvailable;
266 public void onBufferAvailable(Allocation a) {
267 Log.v(TAG, "on Buffer Available");
269 synchronized (this) {
270 mNewFrameAvailable = true;