Kamerayla yakalama oturumları ve istekleri

Not: Bu sayfa Kamera2 paketiyle ilgilidir. Uygulamanız için Kamera2'nin belirli, alt düzey özellikleri gerekmiyorsa, KameraX'i kullanmanızı öneririz. Hem CameraX hem de Camera2, Android 5.0 (API düzeyi 21) ve sonraki sürümleri destekler.

Android destekli tek bir cihazın birden fazla kamerası olabilir. Her kamera bir CameraDevice CameraDevice ise aynı anda birden fazla yayın yapabilir.

Bunun nedenlerinden biri de tek bir akış ile sıralı kamera karelerinin bir CameraDevice cihazındaki vizör, diğerleri ise fotoğraf çekmek veya video çekmek için kullanılabilir Bu akışlar, ham kareleri işleyen paralel ardışık düzenler görevi görür her seferinde tek bir kare atlayıp kameradan çıkın:

Şekil 1. Evrensel Kamera Uygulaması Geliştirme aşaması (Google I/O '18)

Paralel işleme, kullanıcıya bağlı olarak CPU, GPU veya diğer işlemcilerden gelen mevcut işlem gücü. gelen karelere ayak uyduramaz ve bu kareleri bırakmaya başlar.

Her ardışık düzenin kendi çıkış biçimi vardır. Gelen ham veriler, uygun biçime otomatik olarak örtülü mantıka göre çıktı biçimi her bir ardışık düzen ile ilişkilendirilir. Bu sayfa boyunca kullanılan CameraDevice kod örnekleri belirli değildir, bu nedenle önce tanımlayın mevcut tüm kameraları kontrol edin.

CameraDevice kullanarak CameraCaptureSession, oluşturabilirsiniz.CameraDevice Bir CameraDevice, çerçeve yapılandırmasını CameraCaptureSession kullanarak oluşturun. İlgili içeriği oluşturmak için kullanılan yapılandırma, otomatik odaklama, diyafram açıklığı, efektler ve ve maruz kalmayı seçin. Donanım kısıtlamaları nedeniyle yalnızca tek bir yapılandırma Buna kamera sensöründe herhangi bir zamanda aktif olmaya active yapılandırması.

Bununla birlikte, Akış Kullanım Alanları, CameraDevice ürününün önceki yollarını geliştirir ve genişletir. görüntü yakalama oturumlarını canlı oynatabilirsiniz. Bu şekilde kamera akışını optimize edebilirsiniz. kullanım alanına sahip olursunuz. Örneğin, optimizasyon sırasında pil ömrünü uzatabilir görüntülü görüşme de yapabilirsiniz.

CameraCaptureSession, CameraDevice. Oturum oluşturulduğunda ardışık düzen ekleyemez veya kaldıramazsınız. CameraCaptureSession, CaptureRequest, bunlar etkin yapılandırma haline gelir.

CaptureRequest, sıraya bir yapılandırma ekler ve en az bir yapılandırma çerçeve almak için mevcut ardışık düzenlerden birinin veya tümünün CameraDevice. Bir yakalamanın kullanım süresi boyunca çok sayıda yakalama isteği gönderebilirsiniz kabul edilir. Her istek, etkin yapılandırmayı ve çıkış grubunu değiştirebilir ardışık düzenler.

Daha iyi performans için akış kullanım alanlarını kullanın

Akış Kullanım Alanları, Camera2 yakalama performansını artırmanın bir yoludur anlamına gelir. Parametreleri ayarlamak için donanım cihazına daha fazla bilgi verirler. belirli bir göreviniz için daha iyi bir kamera deneyimi sunar.

Bu kamera cihazının, kamera donanımı ve yazılım ardışık düzenlerini optimize etmesini sağlar kullanıcı senaryolarına göre değiştirmeniz gerekir. Akış Kullanımı hakkında daha fazla bilgi için Destek kayıtları için bkz. setStreamUseCase.

Akış Kullanım Alanları belirli bir kamera akışının nasıl kullanılacağını belirtmenizi sağlar oluşturmaya ek olarak, CameraDevice.createCaptureRequest() Bu şekilde, kamera donanımı optimizasyonu hassas ayarlama, sensör modu veya kamera sensörü ayarları gibi belirli kullanım alanları için uygun olan kalite veya gecikme dengeleridir.

Akış Kullanım Alanları şunları içerir:

  • DEFAULT: Mevcut tüm uygulama davranışlarını kapsar. Eşdeğer, akış kullanım alanı ayarlayabilirsiniz.

  • PREVIEW: Vizör veya uygulama içi resim analizi için önerilir.

  • STILL_CAPTURE: Yüksek kaliteli yüksek çözünürlüklü çekim için optimize edilmiştir, ancak önizlemeye benzer kare hızlarını koruması beklenir.

  • VIDEO_RECORD: Yüksek kalite dahil yüksek kaliteli video yakalama için optimize edilmiştir cihaz tarafından destekleniyorsa ve uygulama tarafından etkinleştirilmişse görüntü sabitleme. Bu seçenek, gerçek zamanlıya göre önemli bir gecikmeye yol açan çıkış kareleri üretebilir. Böylece en yüksek kalitede sabitleme veya diğer işleme süreçleri elde edebilirsiniz.

  • VIDEO_CALL: Güç tüketiminin önemli olduğu uzun süreli kamera kullanımları için önerilir. emin olun.

  • PREVIEW_VIDEO_STILL: Sosyal medya uygulamaları veya tek akış kullanımı için önerilir. durumlarda işe yarar. Bu çok amaçlı bir yayın.

  • VENDOR_START: OEM tarafından tanımlanan kullanım alanları için kullanılır.

CameraCaptureSession oluşturma

Kamera oturumu oluşturmak için bir veya daha fazla çıkış arabelleği sağlayın. uygulamanızın çıkış çerçeveleri yazabileceğini lütfen unutmayın. Her arabellek, bir ardışık düzeni temsil eder. Şunu yapmalısınız: çerçevenin yapılandırabilmesi için kamerayı kullanmaya başlamadan önce çerçeveleri göndermek için cihazın dahili ardışık düzenlerini destekler ve bellek arabellekleri ayırır ihtiyaç duyulan çıkış hedeflerine yönlendirirsiniz.

Aşağıdaki kod snippet'inde, iki üçlü kamera oturumuna nasıl hazırlayabileceğiniz çıktı arabellekleri içerir. Bunlardan biri SurfaceView ve başka bir tanesi bir ImageReader. PREVIEW Akış Kullanım Alanı previewSurface ve STILL_CAPTURE Akış Kullanımı Case to imReaderSurface, cihaz donanımının bu akışları bile optimize etmesini sağlar. devam edebilir.

Kotlin

// Retrieve the target surfaces, which might be coming from a number of places:
// 1. SurfaceView, if you want to display the image directly to the user
// 2. ImageReader, if you want to read each frame or perform frame-by-frame
// analysis
// 3. OpenGL Texture or TextureView, although discouraged for maintainability
      reasons
// 4. RenderScript.Allocation, if you want to do parallel processing
val surfaceView = findViewByIdS<urfaceView(>...)
val imageReader = ImageReader.newInstance(...)

// Remember to call this only *after* SurfaceHolder.Callback.surfaceCreated()
val previewSurface = surfaceView.holder.surface
val imReaderSurface = imageReader.surface
val targets = listOf(previewSurface, imReaderSurface)

// Create a capture session using the predefined targets; this also involves
// defining the session state callback to be notified of when the session is
// ready
// Setup Stream Use Case while setting up your Output Configuration.
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
fun configureSession(device: CameraDevice, targets: ListS<urface)>{
    val configs = mutableListOfO<utputConfiguration(>)
    val streamUseCase = CameraMetadata
        .SCALER_AVAILABLE_STREAM_USE_CASES_PREVIEW_VIDEO_STILL

    targets.forEach {
        val config = OutputConfiguration(it)
        config.streamUseCase = streamUseCase.toLong()
        configs.add(config)
    }
    ...
    device.createCaptureSession(session)
}

Java

// Retrieve the target surfaces, which might be coming from a number of places:
// 1. SurfaceView, if you want to display the image directly to the user
// 2. ImageReader, if you want to read each frame or perform frame-by-frame
      analysis
// 3. RenderScript.Allocation, if you want to do parallel processing
// 4. OpenGL Texture or TextureView, although discouraged for maintainability
      reasons
Surface surfaceView = findViewByIdS<urfaceView(>...);
ImageReader imageReader = ImageReader.newInstance(...);

// Remember to call this only *after* SurfaceHolder.Callback.surfaceCreated()
Surface previewSurface = surfaceView.getHolder().getSurface();
Surface imageSurface = imageReader.getSurface();
ListS<urface >targets = Arrays.asList(previewSurface, imageSurface);

// Create a capture session using the predefined targets; this also involves defining the
// session state callback to be notified of when the session is ready
private void configureSession(CameraDevice device, ListS<urface >targets){
    ArrayListO<utputConfiguration >configs= new ArrayList()
    String streamUseCase=  CameraMetadata
        .SCALER_AVAILABLE_STREAM_USE_CASES_PREVIEW_VIDEO_STILL

    for(Surface s : targets){
        OutputConfiguration config = new OutputConfiguration(s)
        config.setStreamUseCase(String.toLong(streamUseCase))
        configs.add(config)
}

device.createCaptureSession(session)
}

Bu noktada, kameranın etkin yapılandırmasını tanımlamadınız. Oturum yapılandırıldığında, yakalamayı oluşturup gönderebilirsiniz. talep ediyorum.

Tamponlara yazılırken girdilere uygulanan dönüşüm her bir hedefin türüne göre belirlenir. Hedef, Surface. Android yapısı, etkin yapılandırmadaki ham bir resmi, şuna uygun bir biçime dönüştürür: her bir hedefe bakın. Dönüşüm, Floodlight etiketindeki piksel biçimi ve boyutu ile kontrol edilir. belirli Surface.

Çerçeve en iyisini yapmaya çalışsa da biraz Surface yapılandırma kombinasyonları çalışmayabilir ve bu da oturum veya deneme bir istek gönderirken çalışma zamanı hatası verebilir veya düşmesine neden olabilir. Bu çerçeve, belli bir ekip üyesiyle cihaz, yüzey ve istek parametrelerinin birleşiminden oluşmuyor. Dokümanlar createCaptureSession() daha fazla bilgi sağlar.

Tek Yakalama İstekleri

Her kare için kullanılan yapılandırma CaptureRequest ile kodlanır. Bu da gönderilir. Bir yakalama isteği oluşturmak için şunlardan birini kullanabilirsiniz: önceden tanımlanmış şablonlar veya tam kontrol için TEMPLATE_MANUAL kullanabilirsiniz. Bir üzerinde kullanılacak bir veya daha fazla çıktı arabelleği sağlamanız talep ediyor. Yalnızca yakalamada önceden tanımlanmış arabellekleri kullanabilirsiniz oturum açın.

Yakalama istekleri bir geliştirici kalıbı ve geliştiricilere, farklı birçok farklı etiket diğer seçenekler de dahildir: otomatik pozlama otomatik odaklama, ve lens diyafram açıklığı. Bir alanı ayarlamadan önce, ilgili seçeneğin telefon ederek cihaz CameraCharacteristics.getAvailableCaptureRequestKeys() ve istenen değerin uygun kamera kontrol edilerek desteklendiğinden emin olun. bir diğer özellik, mevcut otomatik pozlama modları.

Şablonu kullanarak SurfaceView için yakalama isteği oluşturmak istiyorsanız herhangi bir değişiklik yapılmadan önizleme için tasarlandığından, CameraDevice.TEMPLATE_PREVIEW:

Kotlin

val session: CameraCaptureSession = ...  // from CameraCaptureSession.StateCallback
val captureRequest = session.device.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW)
captureRequest.addTarget(previewSurface)

Java

CameraCaptureSession session = ...;  // from CameraCaptureSession.StateCallback
CaptureRequest.Builder captureRequest =
    session.getDevice().createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
captureRequest.addTarget(previewSurface);

Tanımlanmış bir yakalama isteği ile artık görev bunu kamera oturumuna iletebiliriz:

Kotlin

val session: CameraCaptureSession = ...  // from CameraCaptureSession.StateCallback
val captureRequest: CaptureRequest = ...  // from CameraDevice.createCaptureRequest()

// The first null argument corresponds to the capture callback, which you
// provide if you want to retrieve frame metadata or keep track of failed capture
// requests that can indicate dropped frames; the second null argument
// corresponds to the Handler used by the asynchronous callback, which falls
// back to the current thread's looper if null
session.capture(captureRequest.build(), null, null)

Java

CameraCaptureSession session = ...;  // from CameraCaptureSession.StateCallback
CaptureRequest captureRequest = ...;  // from CameraDevice.createCaptureRequest()

// The first null argument corresponds to the capture callback, which you
// provide if you want to retrieve frame metadata or keep track of failed
// capture
// requests that can indicate dropped frames; the second null argument
// corresponds to the Handler used by the asynchronous callback, which falls
// back to the current thread's looper if null
session.capture(captureRequest.build(), null, null);

Belirli bir arabelleğe bir çıkış çerçevesi konulduğunda yakalama geri arama tetiklenir. Birçok durumda, ImageReader.OnImageAvailableListener değeri, içerdiği kare işlendiğinde tetiklenir. Saat: bu noktada resim verilerini belirtilen arabelleğin dışına alabilirsiniz.

Tekrar Yakalama İstekleri

Tek kamera istekleri yapmak kolaydır, ancak canlı bir görüntü göstermek için önizleme veya video eklemek çok kullanışlı değildir. Bu durumda, sürekli bir akış şeklinde çalışır. Aşağıdaki kod snippet'i nasıl eklendiğini gösterir yinelenen istek ekleyin:

Kotlin

val session: CameraCaptureSession = ...  // from CameraCaptureSession.StateCallback
val captureRequest: CaptureRequest = ...  // from CameraDevice.createCaptureRequest()

// This keeps sending the capture request as frequently as possible until
// the
// session is torn down or session.stopRepeating() is called
// session.setRepeatingRequest(captureRequest.build(), null, null)

Java

CameraCaptureSession session = ...;  // from CameraCaptureSession.StateCallback
CaptureRequest captureRequest = ...;  // from CameraDevice.createCaptureRequest()

// This keeps sending the capture request as frequently as possible until the
// session is torn down or session.stopRepeating() is called
// session.setRepeatingRequest(captureRequest.build(), null, null);

Tekrarlanan çekim isteği, kamera cihazının sürekli olarak fotoğraf çekmesine neden oluyor CaptureRequest içindeki ayarları kullanarak resimler. Camera2 API'si Ayrıca, kullanıcıların fotoğraf veya video yükleyerek kameradan video CaptureRequests burada görüldüğü gibi tekrarlanıyor Kamera2 örneği kod deposunu ziyaret edin. Ayrıca, yüksek kaliteli ve yüksek çözünürlüklü yinelenen seri çekimin kullanıldığı yüksek hızlı (yavaş çekim) video CaptureRequests Kamera2 ağır çekim video örnek uygulamasında gösterildiği gibi bulabilirsiniz.

Aralıklı Yakalama İstekleri

Tekrarlanan yakalama isteği etkinken ikinci bir yakalama isteği göndermek için Örneğin, vizör görüntüleyerek kullanıcıların fotoğraf çekmesini sağlayabilirsiniz. Bunu yapmak için devam eden isteği durdurmanızı sağlar. Bunun yerine, tekrarlanmayan bir yakalama yayınlarsınız. isteği gönderir.

Kullanılan çıkış arabelleğinin, kamera oturumunun bir parçası olarak yapılandırılması gerekir oturum ilk oluşturulduğunda. Tekrarlanan isteklerin önceliği, aşağıdaki örneğin çalışmasını sağlayan tek kare veya seri çekim istekleri:

Kotlin

val session: CameraCaptureSession = ...  // from CameraCaptureSession.StateCallback

// Create the repeating request and dispatch it
val repeatingRequest = session.device.createCaptureRequest(
CameraDevice.TEMPLATE_PREVIEW)
repeatingRequest.addTarget(previewSurface)
session.setRepeatingRequest(repeatingRequest.build(), null, null)

// Some time later...

// Create the single request and dispatch it
// NOTE: This can disrupt the ongoing repeating request momentarily
val singleRequest = session.device.createCaptureRequest(
CameraDevice.TEMPLATE_STILL_CAPTURE)
singleRequest.addTarget(imReaderSurface)
session.capture(singleRequest.build(), null, null)

Java

CameraCaptureSession session = ...;  // from CameraCaptureSession.StateCallback

// Create the repeating request and dispatch it
CaptureRequest.Builder repeatingRequest =
session.getDevice().createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
repeatingRequest.addTarget(previewSurface);
session.setRepeatingRequest(repeatingRequest.build(), null, null);

// Some time later...

// Create the single request and dispatch it
// NOTE: This can disrupt the ongoing repeating request momentarily
CaptureRequest.Builder singleRequest =
session.getDevice().createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
singleRequest.addTarget(imReaderSurface);
session.capture(singleRequest.build(), null, null);

Ancak bu yaklaşımın dezavantajı vardır: Tam olarak ne zaman tek istek gerçekleşir. Aşağıdaki şekilde A tekrarlanıyorsa yakalama isteğini gösterir ve B tek kare yakalama isteğidir. oturum, istek sırasını işler:

Şekil 2. Devam eden kamera oturumu için bir istek sırasının görseli

Gelen son yinelenen istek arasındaki gecikmeyle ilgili bir garanti verilmez. B isteği etkinleştirilmeden önce A ve A tekrar kullanıldığında olduğundan bazı kareler atlanır. Paydaşlarla toplantı yaparken ne gerek var?

  • B isteğinde bulunmak için A isteğindeki çıkış hedeflerini ekleyin. Bu şekilde, B'nin çerçevesi hazırdır. Bu çerçeve, A'nın çıkış hedeflerine kopyalanır. Örneğin, her bir görüntüden en iyi şekilde yararlanmaya devam etmek için sabit bir kare hızına sahip olmalıdır. Önceki kodda İsteği oluşturmadan önce singleRequest.addTarget(previewSurface).

  • Bu özel senaryoda kullanılmak üzere tasarlanmış şablonların bir kombinasyonunu kullanın. gecikmeleri devre dışı bırakabilirsiniz.