Camera Preview (Android)

Редактировал(а) Alexandr Fokin 2022/08/04 20:45

 Получение трансляции изображения с камеры устройства Android, с конвертацией кадров в JPEG.

using Android.Hardware;
using Android.Hardware.Camera2;
using Android.Views;
using YuvImage = Android.Graphics.YuvImage;

internal class AndroidCameraProvider
{
   public VideoCaptureContainer CaptureVideo(
        Action<byte[]> onFrameReceive
        )
    {
       var capture = new VideoCaptureContainer(onFrameReceive);
       return capture;
    }


   #region Types

   public class VideoCaptureContainer
    : CameraDal.IVideoCaptureContainer
    {
       //private readonly Action<byte[]> OnFrameReceive;
       private readonly Camera Camera;
       private readonly Handler Handler;


       internal VideoCaptureContainer(
            Action<byte[]> onFrameReceive
            )
        {
           if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.Lollipop)
            {
               throw new NotSupportedException();
            }


           var numberOfCameras = Camera.NumberOfCameras;
           var info = Enumerable.Range(0, numberOfCameras)
                .Select(
                    e =>
                    {
                       var info = new CameraInfo();
                        Camera.GetCameraInfo(e, info);
                       return (Id: e, Info: info);
                    }
                    )
                .ToDictionary(e => e.Id, e => e);

           var cameraId = info.Values
                .First(e => e.Info.Facing == CameraFacing.Back);
           //OnFrameReceive = onFrameReceive;

            Camera = Camera.Open(cameraId.Id);
           var cameraParams = Camera.GetParameters();

           //Format
           var defaultFormat = cameraParams.PreviewFormat;
           var supportedFormats = cameraParams.SupportedPreviewFormats
                .Select(e => (Android.Graphics.ImageFormatType)(int)e)
                .ToHashSet();
           if (!supportedFormats.Contains(Android.Graphics.ImageFormatType.Nv21))
            {
               throw new Exception($"Application Format not supported on device. {Android.Graphics.ImageFormatType.Nv21}");
            }
            cameraParams.PreviewFormat = Android.Graphics.ImageFormatType.Nv21;

           //FrameRate
           var defaultRate = cameraParams.PreviewFrameRate;
           var supportedRates = cameraParams.SupportedPreviewFrameRates
                .Select(e => (int)e)
                .ToHashSet();
           //cameraParams.PreviewFrameRate = supportedRates.Min();
           //cameraParams.PreviewFrameRate = 5;

           //Size
           var defaultSize = cameraParams.PreviewSize;

            Handler = new Handler(
                size: (Width: defaultSize.Width, Height: defaultSize.Height),
                sourceFormat: cameraParams.PreviewFormat,
                onReceive: onFrameReceive
                );

            Camera.SetPreviewCallback(Handler);
            Camera.SetParameters(cameraParams);

            Camera.StartPreview();
        }

       #region Dispose

       private bool disposed = false;

       // реализация интерфейса IDisposable.
       public void Dispose()
        {
            Dispose(true);
           // подавляем финализацию
           GC.SuppressFinalize(this);
        }

       protected void Dispose(bool disposing)
        {
           if (!disposed)
            {
               if (disposing)
                {
                   // Освобождаем управляемые ресурсы
               }
               // освобождаем неуправляемые объекты
               //Handler.OnReceive -= OnFrameReceive;

                Camera.StopPreview();
               //Camera.Release();

                Camera.Dispose();
               //Handler.Dispose();

                disposed = true;
            }
        }

       // Деструктор
       ~VideoCaptureContainer()
        {
            Dispose(false);
        }

       #endregion
   }

   private class Handler
        : Java.Lang.Object,
        Camera.IPreviewCallback
    {
       private readonly Rect rectangle;
       private readonly Android.Graphics.ImageFormatType SourceFormat;
       private readonly Action<byte[]> OnReceive;


       public Handler(
            (int Width, int Height) size,
            Android.Graphics.ImageFormatType sourceFormat,
            Action<byte[]> onReceive
            )
        {
            rectangle = new Rect()
            {
                Bottom = size.Height,
                Top = 0,
                Left = 0,
                Right = size.Width
            };
            SourceFormat = sourceFormat;
            OnReceive = onReceive;
        }


       public void OnPreviewFrame(
           byte[] data,
            Camera camera
            )
        {
           if (OnReceive == null)
            {
               return;
            }

           //Конвертация в нужный формат
           YuvImage image = new YuvImage(
                    yuv: data,
                    format: SourceFormat,
                    width: (int)rectangle.Right,
                    height: (int)rectangle.Bottom,
                    strides: null
                    );
           using (var stream = new MemoryStream())
            {
                image.CompressToJpeg(rectangle, 100, stream);
                data = stream.ToArray();
            }

            OnReceive(data);
        }
    }

   #endregion
}

Камера

How get permission for camera in android.(Specifically Marshmallow)
https://stackoverflow.com/questions/38552144/how-get-permission-for-camera-in-android-specifically-marshmallow

What is the image format in the Preview Screen when Camera is enable
https://stackoverflow.com/questions/23557520/what-is-the-image-format-in-the-preview-screen-when-camera-is-enable

Android: How to save a preview frame as jpeg image?
https://stackoverflow.com/questions/1032258/android-how-to-save-a-preview-frame-as-jpeg-image

jamesathey/FastAndroidCamera
https://github.com/jamesathey/FastAndroidCamera

How To Display A Stream From The Camera Using A TextureView In Xamarin Android App Using Visual Studio 2015
https://www.c-sharpcorner.com/article/how-to-display-a-stream-from-the-camera-using-a-textureview-in-xamarin-android-a/

Теги: