Developer от Бога

DV

четверг, 6 июля 2017 г.

Android. Камера. Android.hardware.camera2

С появлением Android API >21 интерфейс работы с камерой принципиально изменился. В основном причина - совершенствование техники и аппаратного обеспечения которое позволяет дать разработчикам гораздо больше возможностей. Первое что нужно понять - принцип работы функций обратного вызова, которые вызываются не программой, а самой Операционной Системой Android после наступления некоторого события (например - камера готова к использованию или кадр готов к чтению). Все остальное можно понять с краткого описания в документации и примера приложения которое просто открывает камеру, без перегрузки кода пока лишними элементами типа - кнопок, сохранения кадров и т.п. Для начала нужно разобрать минимум действий для запуска камеры.
Пакет Android.hardware.camera2 предоставляет интерфейс для разных устройств-камер, подключенных к Android. Он заменяет устаревший класс  Camera. Классы этого пакета создают потоковый интерфейс, который принимает входные данные запросов для захвата одного кадра, захвата одного изображения с каждого запроса, а затем выводит этот результат, плюс - набор буферов вывода изображений. Запросы обрабатываются таким образом, что несколько запросов может находиться в процессе сразу. Поскольку устройство камеры представляет собой поток из нескольких этапов, имея несколько запросов в одновременно требуется поддерживать полный фреймрейт на большинстве устройств Android.
Ниже перечислены некоторые классы Сamera2:
Типы нужных запросов, а также доступные на устройстве камеры определены в классе CameraManager

CameraDevices предоставляет набор статической информации описывающий аппаратное устройство, доступные параметры и параметры вывода для данного устройства. Эта информация предоставляется через объект CameraCharacteristics, и доступна через getCameraCharacteristics(String).

Для того, чтобы захватить кадр или поток изображений с камеры, приложение должно сначала создать сеанс захвата с набором выходных Surfaces для использования вместе с устройством камеры, с createCaptureSession (List, CameraCaptureSession.StateCallback, Handler). Каждый Surfaces должен быть предварительно сконфигурирован с соответствующим размером и форматом (если это применимо), чтобы соответствовать размерам и форматам, доступные для данной модели камеры. Целевой Surfaces может быть получен из различных классов: SurfaceView, SurfaceTexture  через Surface(SurfaceTexture), MediaCodec, MediaRecorder, Allocation и ImageReader.

Как правило, предварительный просмотр изображений отправляется на SurfaceView или TextureView (через его SurfaceTexture). Захват изображений JPEG или RAW буфера для DngCreator может быть произведен ImageReader с форматами JPEG и RAW_SENSOR. Применение управляемой обработки данных камеры в Renderscript, OpenGL ES, или непосредственно в управляемом машинном коде лучше всего делать с типом YUV, SurfaceTexture и ImageReader с форматом YUV_420_888, соответственно.


После этого приложение должно создать CaptureRequest , который определяет все необходимые параметры для захвата одного изображения. Запрос также перечисляет, какие из сконфигурированных выходных Surfaces следует использовать для этого захвата. CameraDevice имеет собственный метод для создания запроса постройщика (builder) для данного варианта использования, который оптимизирован для работы приложения в Android устройстве.


  1. import android.content.Context;
  2. import android.graphics.ImageFormat;
  3. import android.graphics.SurfaceTexture;
  4. import android.hardware.camera2.CameraAccessException;
  5. import android.hardware.camera2.CameraCaptureSession;
  6. import android.hardware.camera2.CameraDevice;
  7. import android.hardware.camera2.CameraManager;
  8. import android.hardware.camera2.CaptureRequest;
  9. import android.media.ImageReader;
  10. import android.support.v4.content.ContextCompat;
  11. import android.support.v7.app.AppCompatActivity;
  12. import android.os.Bundle;
  13. import android.view.Surface;
  14. import android.view.TextureView;
  15. import android.widget.ImageView;

  16. import java.util.Arrays;

  17. public class MainActivity extends AppCompatActivity {



  18. private CameraDevice mCameraDevice;
  19. private TextureView mTextureView;
  20. private CameraCaptureSession mPreviewCaptureSession;
  21. private CaptureRequest.Builder mCaptureRequestBuilder;



  22. private ImageReader mImageReader = ImageReader.newInstance(1920,1080, ImageFormat.JPEG, 1);

  23. private TextureView.SurfaceTextureListener mSurfaceTextureListener = new TextureView.SurfaceTextureListener() {
  24. @Override
  25. public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {connectCamera();}
  26. @Override public void onSurfaceTextureSizeChanged(SurfaceTexture surface,int width,int height){}
  27. @Override public boolean onSurfaceTextureDestroyed(SurfaceTexture surface){return false;}
  28. @Override public void onSurfaceTextureUpdated(SurfaceTexture surface){}
  29. };


  30. private CameraDevice.StateCallback mCameraDeviceStateCallback = new CameraDevice.StateCallback(){
  31. @Override
  32. public void onOpened(CameraDevice camera) {mCameraDevice = camera; startPreview();}

  33. @Override
  34. public void onDisconnected(CameraDevice camera) { camera.close(); mCameraDevice = null;}

  35. @Override
  36. public void onError(CameraDevice camera, int error) {camera.close(); mCameraDevice = null;}
  37. };


  38. @Override
  39. protected void onCreate(Bundle savedInstanceState) {
  40. super.onCreate(savedInstanceState);
  41. setContentView(R.layout.activity_main);


  42. mTextureView = (TextureView)findViewById(R.id.textureView);
  43. mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
  44. }


  45. private void connectCamera() {
  46. CameraManager cameraManager = (CameraManager)getSystemService(Context.CAMERA_SERVICE);

  47. try { ContextCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA);
  48. cameraManager.openCamera("0", mCameraDeviceStateCallback, null);}
  49. catch (CameraAccessException e) { e.printStackTrace(); }}



  50. CameraCaptureSession.StateCallback run = new CameraCaptureSession.StateCallback(){

  51. @Override
  52. public void onConfigured(CameraCaptureSession session) {

  53. mPreviewCaptureSession = session;

  54. try {mPreviewCaptureSession.setRepeatingRequest(mCaptureRequestBuilder.build(),null, null);}
  55. catch (CameraAccessException e) {e.printStackTrace();}}
  56. @Override
  57. public void onConfigureFailed(CameraCaptureSession session) {}

  58. };

  59. private void startPreview() {
  60. SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture();
  61. surfaceTexture.setDefaultBufferSize(1920,1080);
  62. Surface previewSurface = new Surface(surfaceTexture);

  63. try {
  64. mCaptureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
  65. mCaptureRequestBuilder.addTarget(previewSurface);
  66. mCameraDevice.createCaptureSession(Arrays.asList(previewSurface,mImageReader.getSurface()),run, null);}

  67. catch (CameraAccessException e) {e.printStackTrace();}}

  68. }

Комментариев нет:

Отправить комментарий