Advertisement
Guest User

Untitled

a guest
Oct 23rd, 2016
78
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 19.48 KB | None | 0 0
  1. package com.example.ab.myapplication;
  2.  
  3. import android.Manifest;
  4. import android.app.Service;
  5. import android.content.Context;
  6. import android.content.Intent;
  7. import android.content.pm.PackageManager;
  8. import android.content.res.Configuration;
  9. import android.graphics.ImageFormat;
  10. import android.graphics.Point;
  11. import android.graphics.Rect;
  12. import android.hardware.camera2.CameraAccessException;
  13. import android.hardware.camera2.CameraCaptureSession;
  14. import android.hardware.camera2.CameraCharacteristics;
  15. import android.hardware.camera2.CameraDevice;
  16. import android.hardware.camera2.CameraManager;
  17. import android.hardware.camera2.CaptureFailure;
  18. import android.hardware.camera2.CaptureRequest;
  19. import android.hardware.camera2.CaptureResult;
  20. import android.hardware.camera2.TotalCaptureResult;
  21. import android.hardware.camera2.params.Face;
  22. import android.hardware.camera2.params.StreamConfigurationMap;
  23. import android.media.Image;
  24. import android.media.ImageReader;
  25. import android.net.Uri;
  26. import android.os.Handler;
  27. import android.os.HandlerThread;
  28. import android.os.IBinder;
  29. import android.os.Process;
  30. import android.support.annotation.IntDef;
  31. import android.support.v4.app.ActivityCompat;
  32. import android.util.Log;
  33. import android.util.Size;
  34. import android.view.Surface;
  35.  
  36. import java.io.IOException;
  37. import java.lang.annotation.Retention;
  38. import java.nio.ByteBuffer;
  39. import java.util.Arrays;
  40. import java.util.Collections;
  41. import java.util.concurrent.TimeUnit;
  42.  
  43. import static java.lang.annotation.RetentionPolicy.SOURCE;
  44.  
  45. abstract public class CameraService extends Service {
  46. public static final String SCHEME = "camera";
  47. public static final int IMAGE_FORMAT = ImageFormat.RAW10;
  48. public static final int REQUIRED_FEATURE = CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW;
  49. private Integer FACE_DETECTION_MODE = -1;
  50.  
  51. @Retention(SOURCE)
  52. @IntDef({CAMERA_ACCESS_EXCEPTION, NO_CAMERA_PERMISSION, CAMERA_STATE_ERROR,
  53. CAPTURE_SESSION_CONFIGURE_FAILED, CAPTURE_SESSION_CONFIGURE_EXCEPTION, SERVICE_START_ERROR})
  54. public @interface CameraError {}
  55. public static final int CAMERA_ACCESS_EXCEPTION = 0;
  56. public static final int NO_CAMERA_PERMISSION = 1;
  57. public static final int CAMERA_STATE_ERROR = 2;
  58. public static final int CAPTURE_SESSION_CONFIGURE_FAILED = 3;
  59. public static final int CAPTURE_SESSION_CONFIGURE_EXCEPTION = 4;
  60. public static final int SERVICE_START_ERROR = 5;
  61.  
  62. private static final int SERVICE_START_MODE = START_NOT_STICKY;
  63.  
  64. private final String TAG;
  65. public final String CAMERA_ID;
  66. public final Uri BASE;
  67.  
  68. private Size frameSize;
  69. private final HandlerThread SERVICE_MAIN_THREAD;
  70. private CameraAvailabilityManager mCameraAvailabilityManager;
  71.  
  72. public CameraService() {
  73. TAG = getClass().getName();
  74. int p = TAG.indexOf('_');
  75. if (p < CameraService.class.getSimpleName().length()) {
  76. throw new RuntimeException("Invalid class name");
  77. }
  78. CAMERA_ID = TAG.substring(p + 1);
  79. BASE = new Uri.Builder().scheme(SCHEME).authority(CAMERA_ID).build();
  80. SERVICE_MAIN_THREAD = new HandlerThread(TAG + " main thread");
  81. SERVICE_MAIN_THREAD.start();
  82. Log.d(TAG, "constructor... " + this);
  83. }
  84.  
  85. @Override
  86. public IBinder onBind(Intent intent) {
  87. throw new UnsupportedOperationException("Not implemented");
  88. }
  89.  
  90. /**
  91. * Start camera.
  92. * TODO:
  93. * - config
  94. * - onError () ->
  95. * - check camera capabilities () ->
  96. * -
  97. * @param intent
  98. * @param flags
  99. * @param startId
  100. * @return
  101. */
  102. @Override
  103. public int onStartCommand(Intent intent, int flags, int startId) {
  104. if (mCameraAvailabilityManager != null) {
  105. Log.d(TAG, "onStartCommand() ignoring repeating start " + intent);
  106. return SERVICE_START_MODE;
  107. }
  108. try {
  109. Log.d(TAG, "onStartCommand()... " + this);
  110. final CameraManager cm = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
  111. if (!Arrays.asList(cm.getCameraIdList()).contains(CAMERA_ID)) {
  112. throw new RuntimeException("camera " + CAMERA_ID + " is not on the CameraManager list");
  113. }
  114. CameraCharacteristics chars = cm.getCameraCharacteristics(CAMERA_ID);
  115. int[] caps = chars.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
  116. Arrays.sort(caps);
  117.  
  118. { // check capabilities
  119. if (Arrays.binarySearch(caps, REQUIRED_FEATURE) < 0) {
  120. throw new CameraAccessException(CameraAccessException.CAMERA_ERROR,
  121. "camera " + CAMERA_ID + " does not support feature " + REQUIRED_FEATURE);
  122. }
  123. StreamConfigurationMap map = chars.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
  124. Size[] sizes = map.getOutputSizes(IMAGE_FORMAT);
  125. if (sizes == null) {
  126. throw new RuntimeException("camera " + CAMERA_ID + " does not have sizes for image format " + IMAGE_FORMAT);
  127. }
  128. frameSize = Collections.max(Arrays.asList(sizes),
  129. (l, r) -> Integer.signum(l.getWidth() * l.getHeight() - r.getWidth() * r.getHeight()));
  130. int[] fd = chars.get(CameraCharacteristics.STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES);
  131. int maxFd = chars.get(CameraCharacteristics.STATISTICS_INFO_MAX_FACE_COUNT);
  132. if (maxFd > 0) {
  133. Arrays.sort(fd);
  134. FACE_DETECTION_MODE = fd[fd.length - 1];
  135. }
  136. Log.d(TAG, "fase detection modes " + fd.length + ", max = " + maxFd);
  137. }
  138. mCameraAvailabilityManager = new CameraAvailabilityManager();
  139. cm.registerAvailabilityCallback(mCameraAvailabilityManager, new Handler(SERVICE_MAIN_THREAD.getLooper()));
  140. broadcast("service started for camera " + CAMERA_ID);
  141. return SERVICE_START_MODE;
  142. } catch (CameraAccessException e) {
  143. e.printStackTrace();
  144. broadcast("service start faled for camera " + CAMERA_ID);
  145. { // onError
  146. reportError(SERVICE_START_ERROR, e);
  147. }
  148. Log.e(TAG, "onStartCommand() failed " + intent);
  149. }
  150. return START_NOT_STICKY;
  151. }
  152.  
  153. @Override
  154. public void onDestroy() {
  155. super.onDestroy();
  156. Log.d(TAG, "onDestroy() " + this);
  157. ((CameraManager) getSystemService(Context.CAMERA_SERVICE)).unregisterAvailabilityCallback(mCameraAvailabilityManager);
  158. SERVICE_MAIN_THREAD.quitSafely();
  159. mCameraAvailabilityManager.destroy();
  160. }
  161.  
  162. private class CameraAvailabilityManager extends CameraManager.AvailabilityCallback {
  163. final String TAG = CameraAvailabilityManager.class.getName();
  164. private CameraStateManager mCameraStateManager;
  165.  
  166. @Override
  167. public void onCameraAvailable(String cameraId) {
  168. if (!CAMERA_ID.equals(cameraId)) {
  169. return;
  170. }
  171. Log.d(TAG, "onCameraAvailable()... " + cameraId);
  172. try {
  173. if (ActivityCompat.checkSelfPermission(getApplication(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
  174. throw new IllegalAccessException ("No camera permission granted");
  175. }
  176. mCameraStateManager = new CameraStateManager();
  177. ((CameraManager)getSystemService(Context.CAMERA_SERVICE)).openCamera(cameraId, mCameraStateManager, null);
  178. Log.d(TAG, "onCameraAvailable() submited request to open camera " + cameraId);
  179. return;
  180. } catch (CameraAccessException e) {
  181. reportError(CAMERA_ACCESS_EXCEPTION, e);
  182. } catch (IllegalAccessException e) {
  183. reportError(NO_CAMERA_PERMISSION, e);
  184. }
  185. broadcast("Failed to open camera " + CAMERA_ID);
  186. destroy();
  187. }
  188.  
  189. @Override
  190. public void onCameraUnavailable(String cameraId) {
  191. if (!CAMERA_ID.equals(cameraId)) {
  192. return;
  193. }
  194. broadcast("Camera " + CAMERA_ID + " unavailable");
  195. // ignore because we get it when we open camera
  196. // destroy();
  197. }
  198.  
  199. public void destroy() {
  200. if (mCameraStateManager != null) {
  201. mCameraStateManager.destroy(null);
  202. }
  203. }
  204. }
  205.  
  206. /*
  207. * Takes care of camera life cycle events: connected, disconnected, errors.
  208. */
  209. private class CameraStateManager extends CameraDevice.StateCallback {
  210. final String TAG = CameraStateManager.class.getName();
  211. private CaptureSessionManager mSessionManager;
  212.  
  213. @Override
  214. public void onOpened(CameraDevice camera) {
  215. Log.d(TAG, "onOpened() " + camera.getId());
  216. try {
  217. mSessionManager = new CaptureSessionManager(camera);
  218. } catch (CameraAccessException | IllegalAccessException e) {
  219. e.printStackTrace();
  220. reportError(CAMERA_ACCESS_EXCEPTION, e);
  221. destroy(camera);
  222. stopSelf();
  223. }
  224. }
  225.  
  226. @Override
  227. public void onDisconnected(CameraDevice camera) {
  228. Log.d(TAG, "disconnected " + camera.getId());
  229. destroy(camera);
  230. }
  231.  
  232. @Override
  233. public void onError(CameraDevice camera, int error) {
  234. // TODO: verbose error
  235. Log.d(TAG, "error in " + camera.getId() + ": " + error);
  236. reportError(CAMERA_STATE_ERROR, new Exception("camera device " + camera.getId() + " error " + error));
  237. }
  238.  
  239. private void destroy(CameraDevice camera) {
  240. if (mSessionManager != null) {
  241. mSessionManager.destroy();
  242. mSessionManager = null;
  243. }
  244. if (camera != null) {
  245. camera.close();
  246. }
  247. }
  248. }
  249.  
  250. /**
  251. * Camera session creation and life cycle management: configured, failed, closed
  252. */
  253. private class CaptureSessionManager extends CameraCaptureSession.StateCallback {
  254. final String TAG = CaptureSessionManager.class.getName();
  255. final private HandlerThread imageProducer = new HandlerThread("Image producer callback thread",
  256. Process.THREAD_PRIORITY_URGENT_DISPLAY);
  257. final private HandlerThread captureRequestCallbackThread = new HandlerThread("Capture request callback thread",
  258. Process.THREAD_PRIORITY_URGENT_DISPLAY);
  259. final private HandlerThread sessionCallbackThread = new HandlerThread("Capture session callback thread",
  260. Process.THREAD_PRIORITY_DEFAULT);
  261.  
  262. final private CameraDevice mCamera;
  263. final private ImageReader mImage;
  264. private CameraCaptureSession mSession;
  265.  
  266. public CaptureSessionManager(CameraDevice camera) throws IllegalAccessException, CameraAccessException {
  267. mCamera = camera;
  268. sessionCallbackThread.start();
  269. mImage = ImageReader.newInstance(frameSize.getWidth(), frameSize.getHeight(), IMAGE_FORMAT, /*maxImages*/ 5);
  270. camera.createCaptureSession(Arrays.asList(mImage.getSurface()), this, new Handler(sessionCallbackThread.getLooper()));
  271. captureRequestCallbackThread.start();
  272. imageProducer.start();
  273. }
  274.  
  275. @Override
  276. public void onConfigured(CameraCaptureSession session) {
  277. try {
  278. mSession = session;
  279. final CaptureRequest.Builder rb = mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
  280. rb.addTarget(mImage.getSurface());
  281. if (FACE_DETECTION_MODE >= 0) {
  282. rb.set(CaptureRequest.STATISTICS_FACE_DETECT_MODE, FACE_DETECTION_MODE);
  283. }
  284. session.setRepeatingRequest(rb.build(), new CaptureCallbackManager(), new Handler(captureRequestCallbackThread.getLooper()));
  285. // session.setRepeatingRequest(rb.build(), null, null);
  286. mImage.setOnImageAvailableListener(new ImageAvailabeManager(), new Handler(imageProducer.getLooper()));
  287. Log.e(TAG, "session configured: " + session);
  288. } catch (CameraAccessException | IllegalStateException e) {
  289. e.printStackTrace();
  290. reportError(CAPTURE_SESSION_CONFIGURE_EXCEPTION, new Exception("onConfigureFailed(), session " + session));
  291. destroy();
  292. }
  293. }
  294.  
  295. @Override
  296. public void onClosed(CameraCaptureSession session) {
  297. Log.e(TAG, "session callback onClosed() " + session);
  298. destroy();
  299. }
  300.  
  301. @Override
  302. public void onConfigureFailed(CameraCaptureSession session) {
  303. Log.e(TAG, "session callback onConfigureFailed() " + session);
  304. reportError(CAPTURE_SESSION_CONFIGURE_FAILED, new Exception("onConfigureFailed(), session " + session));
  305. destroy();
  306. }
  307.  
  308. public void destroy() {
  309. if (mSession != null) {
  310. mSession.close();
  311. }
  312. mImage.close();
  313. imageProducer.quitSafely();
  314. captureRequestCallbackThread.quitSafely();
  315. sessionCallbackThread.quitSafely();
  316. mCamera.close();
  317. }
  318. }
  319.  
  320. /**
  321. * Frame metadata handler: exposure, faces, much more ...
  322. */
  323. private class CaptureCallbackManager extends CameraCaptureSession.CaptureCallback {
  324. final String TAG = CaptureCallbackManager.class.getName();
  325. @Override
  326. public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
  327. // TODO: grab metada data
  328. Integer afState = result.get(CaptureResult.CONTROL_AF_STATE);
  329. long counter = result.getFrameNumber();
  330. Long ns = result.get(CaptureResult.SENSOR_EXPOSURE_TIME);
  331. long ms = TimeUnit.MILLISECONDS.convert(ns, TimeUnit.NANOSECONDS);
  332. // Log.d(TAG, "capture completed " + counter + ", exposure = " + ms);
  333. Integer mode = result.get(CaptureResult.STATISTICS_FACE_DETECT_MODE);
  334. Face[] faces = result.get(CaptureResult.STATISTICS_FACES);
  335. // Log.e(TAG, "faces : " + faces.length + " , mode : " + mode);
  336. for (Face face : faces) {
  337. Rect bounds = face.getBounds();
  338. Point leftEye = face.getLeftEyePosition();
  339. Point rightEye = face.getRightEyePosition();
  340. Point mouth = face.getMouthPosition();
  341. Log.e(TAG, String.format("b:%s, l:%s, r:%s, m:%s", bounds, leftEye, rightEye, mouth));
  342. }
  343. }
  344.  
  345. @Override
  346. public void onCaptureBufferLost(CameraCaptureSession session, CaptureRequest request, Surface target, long frameNumber) {
  347. Log.d(TAG, "capture buffer lost " + frameNumber);
  348. }
  349.  
  350. @Override
  351. public void onCaptureFailed(CameraCaptureSession session, CaptureRequest request, CaptureFailure failure) {
  352. Log.d(TAG, "onCaptureFailed " + failure.getFrameNumber());
  353. }
  354.  
  355. @Override
  356. public void onCaptureSequenceAborted(CameraCaptureSession session, int sequenceId) {
  357. Log.d(TAG, "onCaptureSequenceAborted " + sequenceId);
  358. }
  359.  
  360. @Override
  361. public void onCaptureStarted(CameraCaptureSession session, CaptureRequest request, long timestamp, long frameNumber) {
  362. // Log.d(TAG, "onCaptureStarted " + frameNumber);
  363. }
  364.  
  365. @Override
  366. public void onCaptureSequenceCompleted(CameraCaptureSession session, int sequenceId, long frameNumber) {
  367. Log.d(TAG, "onCaptureSequenceCompleted " + frameNumber);
  368. }
  369.  
  370. @Override
  371. public void onCaptureProgressed(CameraCaptureSession session, CaptureRequest request, CaptureResult partialResult) {
  372. Log.d(TAG, "onCaptureProgressed " + partialResult.getFrameNumber());
  373. }
  374. }
  375.  
  376. /**
  377. * Frame data handler
  378. */
  379. private class ImageAvailabeManager implements ImageReader.OnImageAvailableListener {
  380. final String TAG = ImageAvailabeManager.class.getName();
  381. private int mFrameCount = 0;
  382. private long t = System.currentTimeMillis();
  383.  
  384. @Override
  385. public void onImageAvailable(ImageReader reader) {
  386. try {
  387. Image frame = reader.acquireNextImage();
  388. if (frame.getFormat() == IMAGE_FORMAT) {
  389. try {
  390. processRawImage(frame);
  391. } catch (IOException e) {
  392. e.printStackTrace();
  393. } finally {
  394. frame.close();
  395. }
  396. } else {
  397. Log.e(TAG, "Unexpected image format");
  398. }
  399. } catch (IllegalStateException e) {
  400. Log.e(TAG, "Too many images queued for saving, dropping image for request: ");
  401. }
  402. }
  403.  
  404. private void processRawImage(Image raw) throws IOException {
  405. // Log.d(TAG, "processRawImage()");
  406. int format = raw.getFormat();
  407. if (format != IMAGE_FORMAT) {
  408. throw new IllegalArgumentException("Supports only RAW format" + format);
  409. }
  410. Image.Plane[] planes = raw.getPlanes();
  411. ByteBuffer buf = planes[0].getBuffer();
  412. int w = raw.getWidth();
  413. int h = raw.getHeight();
  414. int ps = planes[0].getPixelStride();
  415. int rs = planes[0].getRowStride();
  416. int off = 0;
  417. long capacity = buf.capacity();
  418. long totalSize = ((long) rs) * h + off;
  419. int minRowStride = ps * w;
  420. mFrameCount++;
  421. if (mFrameCount >= 100) {
  422. long dt = (System.currentTimeMillis() - t);
  423. Log.d(TAG, String.format("%d frames %dx%d pixels %d bytes in %d ms", mFrameCount, w, h, capacity, dt));
  424. mFrameCount = 0;
  425. t = System.currentTimeMillis();
  426. }
  427. // TODO:
  428. buf.clear(); // Reset mark and limit
  429. }
  430.  
  431. }
  432.  
  433. protected void reportError(@CameraError int error, Exception ex) {
  434. ex.printStackTrace();
  435. String msg = ex.getMessage();
  436. switch(error) {
  437. case CAMERA_ACCESS_EXCEPTION:
  438. Log.e(TAG, "CAMERA_ACCESS_EXCEPTION: " + msg);
  439. break;
  440. case NO_CAMERA_PERMISSION:
  441. Log.e(TAG, "NO_CAMERA_PERMISSION: " + msg);
  442. break;
  443. case CAMERA_STATE_ERROR:
  444. Log.e(TAG, "CAMERA_STATE_ERROR: " + msg);
  445. break;
  446. case CAPTURE_SESSION_CONFIGURE_FAILED:
  447. Log.e(TAG, "CAPTURE_SESSION_CONFIGURE_FAILED: " + msg);
  448. break;
  449. default:
  450. Log.e(TAG, "UNKNOWN ERROR " + error + ": " + msg);
  451. break;
  452. }
  453. }
  454.  
  455. protected void broadcast(String msg) {
  456. Intent intent = new Intent(TAG, Uri.withAppendedPath(BASE, msg));
  457. getApplication().sendBroadcast(intent);
  458. Log.d(TAG, "broadcast: " + msg);
  459. }
  460.  
  461. // TODO:
  462. // TODO: unhandled exception handler
  463.  
  464. @Override
  465. public void onConfigurationChanged(Configuration newConfig) {
  466. }
  467.  
  468. @Override
  469. public void onLowMemory() {
  470. }
  471.  
  472. @Override
  473. public void onTrimMemory(int level) {
  474. }
  475.  
  476. private boolean isSelfieCamera(String cameraId) throws CameraAccessException {
  477. final CameraManager cm = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
  478. CameraCharacteristics chars = cm.getCameraCharacteristics(cameraId);
  479. return chars.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT;
  480. }
  481. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement