Tiện ích Camera

Nhà sản xuất thiết bị có thể hiển thị các tiện ích như hiệu ứng bokeh, chế độ ban đêm và HDR cho nhà phát triển bên thứ ba thông qua giao diện Tiện ích máy ảnh do thư viện nhà cung cấp OEM cung cấp. Nhà phát triển có thể sử dụng API tiện ích Camera2API tiện ích CameraX để truy cập vào các tiện ích được triển khai trong thư viện nhà cung cấp OEM.

Để biết danh sách các tiện ích được hỗ trợ, giống nhau trên Camera2 và CameraX, hãy xem CameraX Extensions API. Nếu bạn muốn thêm một tiện ích, hãy gửi lỗi bằng Công cụ theo dõi lỗi.

Trang này mô tả cách triển khai và bật thư viện nhà cung cấp OEM trên các thiết bị.

Kiến trúc

Sơ đồ sau đây mô tả cấu trúc của giao diện Tiện ích máy ảnh hoặc extensions-interface: Kiến trúc

Hình 1. Sơ đồ cấu trúc của Tiện ích máy ảnh

Như minh hoạ trong sơ đồ, để hỗ trợ Tiện ích máy ảnh, bạn cần triển khai extensions-interface do thư viện nhà cung cấp OEM cung cấp. Thư viện nhà cung cấp OEM của bạn cho phép hai API: CameraX Extensions API (API tiện ích CameraX) và Camera2 Extensions API (API tiện ích Camera2). Các API này lần lượt được ứng dụng CameraX và Camera2 sử dụng để truy cập vào tiện ích của nhà cung cấp.

Triển khai thư viện nhà cung cấp OEM

Để triển khai thư viện nhà cung cấp OEM, hãy sao chép các tệp camera-extensions-stub vào dự án thư viện hệ thống. Các tệp này xác định giao diện Tiện ích máy ảnh.

Các tệp camera-extensions-stub được chia thành các danh mục sau:

Tệp giao diện thiết yếu (không sửa đổi)

  • PreviewExtenderImpl.java
  • ImageCaptureExtenderImpl.java
  • ExtenderStateListener.java
  • ProcessorImpl.java
  • PreviewImageProcessorImpl.java
  • CaptureProcessorImpl.java
  • CaptureStageImpl.java
  • RequestUpdateProcessorImpl.java
  • ProcessResultImpl.java
  • advanced/AdvancedExtenderImpl.java
  • advanced/Camera2OutputConfigImpl.java
  • advanced/Camera2SessionConfigImpl.java
  • advanced/ImageProcessorImpl.java
  • advanced/ImageReaderOutputConfigImpl.java
  • advanced/ImageReferenceImpl.java
  • advanced/MultiResolutionImageReaderOutputConfigImpl.java
  • advanced/OutputSurfaceImpl.java
  • advanced/RequestProcessorImpl.java
  • advanced/SessionProcessorImpl.java
  • advanced/SurfaceOutputConfigImpl.java

Các cách triển khai bắt buộc (thêm cách triển khai của bạn)

  • ExtensionVersionImpl.java
  • InitializerImpl.java

Các lớp mở rộng Bokeh (triển khai lớp này nếu tiện ích Bokeh được hỗ trợ)

  • BokehImageCaptureExtenderImpl.java
  • BokehPreviewExtenderImpl.java
  • advanced/BokehAdvancedExtenderImpl.java

Các lớp tiện ích mở rộng chế độ ban đêm (triển khai nếu tiện ích mở rộng chế độ ban đêm được hỗ trợ)

  • NightImageCaptureExtenderImpl.java
  • NightPreviewExtenderImpl.java
  • advanced/NightAdvancedExtenderImpl.java

Các lớp trình mở rộng tự động (triển khai lớp này nếu Trình mở rộng tự động được hỗ trợ)

  • AutoImageCaptureExtenderImpl.java
  • AutoPreviewExtenderImpl.java
  • advanced/AutoAdvancedExtenderImpl.java

Các lớp mở rộng HDR (triển khai lớp này nếu tiện ích HDR được hỗ trợ)

  • HdrImageCaptureExtenderImpl.java
  • HdrPreviewExtenderImpl.java
  • advanced/HdrAdvancedExtenderImpl.java

Các lớp mở rộng tính năng Làm đẹp khuôn mặt (triển khai lớp này nếu tiện ích Làm đẹp khuôn mặt được hỗ trợ)

  • BeautyImageCaptureExtenderImpl.java
  • BeautyPreviewExtenderImpl.java
  • advanced/BeautyAdvancedExtenderImpl.java

Tiện ích (không bắt buộc, có thể xoá)

  • advanced/Camera2OutputConfigImplBuilder.java
  • advanced/Camera2SessionConfigImplBuilder.java

Bạn không bắt buộc phải cung cấp phương thức triển khai cho mọi tiện ích. Nếu bạn không triển khai tiện ích, hãy đặt isExtensionAvailable() để trả về false hoặc xoá các lớp Extender tương ứng. API Tiện ích Camera2 và CameraX báo cáo cho ứng dụng rằng tiện ích không dùng được.

Hãy cùng tìm hiểu cách API Tiện ích Camera2 và CameraX tương tác với thư viện nhà cung cấp để bật một tiện ích. Sơ đồ sau đây minh hoạ quy trình toàn diện bằng cách lấy tiện ích Chế độ ban đêm làm ví dụ:

Mainflow

Hình 2. Triển khai tiện ích ban đêm

  1. Xác minh phiên bản:

    Camera2/X gọi ExtensionVersionImpl.checkApiVersion() để đảm bảo rằng phiên bản extensions-interface do OEM triển khai tương thích với các phiên bản được hỗ trợ Camera2/X.

  2. Khởi chạy thư viện của nhà cung cấp:

    InitializerImpl có một phương thức init() khởi chạy thư viện nhà cung cấp. Camera2/X hoàn tất quá trình khởi chạy trước khi truy cập vào các lớp Extender.

  3. Tạo bản sao các lớp Tiện ích:

    Tạo bản sao các lớp Extender cho tiện ích. Có hai loại Trình mở rộng: Trình mở rộng cơ bản và Trình mở rộng nâng cao. Bạn phải triển khai một loại Tiện ích mở rộng cho tất cả Tiện ích. Để biết thêm thông tin, hãy xem phần Trình mở rộng cơ bản so với Trình mở rộng nâng cao.

    Camera2/X tạo bản sao và tương tác với các lớp Extender để truy xuất thông tin và bật tiện ích. Đối với một tiện ích nhất định, Camera2/X có thể tạo bản sao cho các lớp Extender nhiều lần. Do đó, đừng thực hiện quá trình khởi tạo nặng trong hàm khởi tạo hoặc lệnh gọi init(). Chỉ thực hiện các thao tác nặng khi phiên máy ảnh sắp bắt đầu, chẳng hạn như khi onInit() được gọi trong Trình mở rộng cơ bản hoặc initSession() được gọi trong Trình mở rộng nâng cao.

    Đối với tiện ích ban đêm, các lớp Extender sau đây được tạo bản sao cho loại Extender cơ bản:

    • NightImageCaptureExtenderImpl.java
    • NightPreviewExtenderImpl.java

    Và đối với loại Trình mở rộng nâng cao:

    • NightAdvancedExtenderImpl.java
  4. Kiểm tra tình trạng có sẵn của tiện ích:

    Trước khi bật tiện ích, isExtensionAvailable() sẽ kiểm tra xem có thể sử dụng tiện ích trên mã nhận dạng máy ảnh đã chỉ định hay không thông qua thực thể Extender.

  5. Khởi chạy Trình mở rộng bằng thông tin máy ảnh:

    Camera2/X gọi init() trên thực thể Extender và truyền cho thực thể này mã nhận dạng máy ảnh và CameraCharacteristics.

  6. Thông tin truy vấn:

    Gọi lớp Extender để truy xuất thông tin như độ phân giải được hỗ trợ, vẫn ghi lại độ trễ ước tính và ghi lại khoá yêu cầu từ Extender để chuẩn bị bật tiện ích.

  7. Bật tiện ích trên Trình mở rộng:

    Lớp Extender cung cấp tất cả giao diện cần thiết để bật lớp này. API này cung cấp một cơ chế để liên kết việc triển khai OEM vào quy trình Camera2, chẳng hạn như chèn các tham số yêu cầu chụp hoặc bật bộ xử lý hậu kỳ.

    Đối với loại Tiện ích mở rộng nâng cao, Camera2/X tương tác với SessionProcessorImpl để bật tiện ích. Camera2/X truy xuất thực thể SessionProcessorImpl bằng cách gọi createSessionProcessor() trên Trình mở rộng.

Các phần sau đây mô tả chi tiết hơn về quy trình mở rộng.

Xác minh phiên bản

Khi tải thư viện nhà cung cấp OEM từ thiết bị trong thời gian chạy, Camera2/X sẽ xác minh xem thư viện có tương thích với phiên bản extensions-interface hay không. extensions-interface sử dụng định nghĩa phiên bản ngữ nghĩa hoặc MAJOR.MINOR.PATCH, ví dụ: 1.1.0 hoặc 1.2.0. Tuy nhiên, chỉ phiên bản chính và phiên bản phụ mới được dùng trong quá trình xác minh phiên bản.

Để xác minh phiên bản, Camera2/X gọi ExtensionVersionImpl.checkApiVersion() bằng phiên bản extensions-interface được hỗ trợ. Sau đó, Camera2/X sẽ sử dụng phiên bản do thư viện OEM báo cáo để xác định xem có thể bật tiện ích hay không và tiện ích đó sẽ gọi những chức năng nào.

Khả năng tương thích với phiên bản lớn

Nếu các phiên bản chính của giao diện tiện ích khác nhau giữa Camera2/X và thư viện nhà cung cấp, thì giao diện đó sẽ được coi là không tương thích và tiện ích sẽ bị tắt.

Khả năng tương thích ngược

Miễn là phiên bản chính giống nhau, Camera2/X sẽ đảm bảo khả năng tương thích ngược với các thư viện của nhà cung cấp OEM được tạo bằng các phiên bản extensions-interface trước đó. Ví dụ: nếu Camera2/X hỗ trợ extensions-interface 1.3.0, thì các thư viện nhà cung cấp OEM đã triển khai 1.0.0, 1.1.0 và 1.2.0 vẫn tương thích. Điều này cũng có nghĩa là sau khi bạn triển khai một phiên bản cụ thể của thư viện nhà cung cấp, Camera2/X sẽ đảm bảo thư viện tương thích ngược với các phiên bản extension-interface sắp tới.

Khả năng tương thích chuyển tiếp

Khả năng tương thích chuyển tiếp với thư viện nhà cung cấp của extensions-interface mới hơn phụ thuộc vào bạn, nhà sản xuất thiết bị gốc (OEM). Nếu cần một số tính năng để triển khai tiện ích, bạn nên bật tiện ích bắt đầu từ một phiên bản nhất định. Trong trường hợp này, bạn có thể trả về phiên bản extensions-interface được hỗ trợ khi phiên bản thư viện Camera2/X đáp ứng các yêu cầu. Nếu các phiên bản Camera2/X không được hỗ trợ, bạn có thể trả về một phiên bản không tương thích như 99.0.0 để tắt các tiện ích.

Khởi chạy thư viện của nhà cung cấp

Sau khi xác minh phiên bản extensions-interface do thư viện OEM triển khai, Camera2/X sẽ bắt đầu quá trình khởi chạy. Phương thức InitializerImpl.init() sẽ báo cho thư viện OEM biết rằng một ứng dụng đang cố gắng sử dụng các tiện ích.

Camera2/X không thực hiện lệnh gọi nào khác đến thư viện OEM (ngoài việc kiểm tra phiên bản) cho đến khi thư viện nhà cung cấp OEM gọi OnExtensionsInitializedCallback.onSuccess() để thông báo quá trình khởi chạy đã hoàn tất.

Bạn phải triển khai InitializerImpl kể từ extensions-interface 1.1.0. Camera2/X sẽ bỏ qua bước khởi chạy thư viện nếu thư viện nhà cung cấp OEM triển khai extensions-interface 1.0.0.

Trình mở rộng cơ bản so với Trình mở rộng nâng cao

Có hai loại triển khai extensions-interface: Trình mở rộng cơ bản và Trình mở rộng nâng cao. Trình mở rộng nâng cao được hỗ trợ kể từ phiên bản extensions-interface 1.2.0.

Triển khai Trình mở rộng cơ bản cho các tiện ích xử lý hình ảnh trong HAL máy ảnh hoặc sử dụng trình xử lý hậu kỳ có thể xử lý luồng YUV.

Triển khai Trình mở rộng nâng cao cho các tiện ích cần tuỳ chỉnh cấu hình luồng Camera2 và gửi yêu cầu chụp nếu cần.

Hãy xem bảng sau để so sánh:

Trình mở rộng cơ bản Trình mở rộng nâng cao
Cấu hình luồng Đã khắc phục
Xem trước: PRIVATE hoặc YUV_420_888 (nếu có bộ xử lý)
Chụp ảnh tĩnh: JPEG hoặc YUV_420_888 (nếu có bộ xử lý)
Nhà sản xuất thiết bị gốc (OEM) có thể tuỳ chỉnh.
Gửi yêu cầu chụp Chỉ Camera2/X mới có thể gửi yêu cầu chụp. Bạn có thể đặt các tham số cho các yêu cầu này. Khi bộ xử lý được cung cấp để chụp ảnh, Camera2/X có thể gửi nhiều yêu cầu chụp và gửi tất cả hình ảnh cũng như kết quả chụp đến bộ xử lý. Bạn sẽ được cung cấp một thực thể RequestProcessorImpl để thực thi yêu cầu chụp camera2 và nhận kết quả cũng như Hình ảnh.

Camera2/X gọi startRepeatingstartCapture trên SessionProcessorImpl để báo hiệu cho OEM bắt đầu yêu cầu lặp lại để xem trước và bắt đầu trình tự chụp ảnh tĩnh tương ứng.

Hook trong quy trình máy ảnh
  • onPresetSession cung cấp các tham số phiên.
  • onEnableSession gửi một yêu cầu ngay sau khi CameraCaptureSession được định cấu hình.
  • onDisableSession gửi một yêu cầu trước khi CameraCaptureSession đóng.
  • initSession khởi chạy và trả về cấu hình phiên camera2 được tuỳ chỉnh để tạo phiên chụp.
  • onCaptureSessionStart được gọi ngay sau khi CameraCaptureSession được định cấu hình.
  • onCaptureSessionEnd được gọi trước khi CameraCaptureSession đóng.
Phù hợp với Các tiện ích được triển khai trong HAL máy ảnh hoặc trong một bộ xử lý xử lý hình ảnh YUV.
  • Có các phương thức triển khai dựa trên Camera2 cho các tiện ích.
  • Cần cấu hình luồng tuỳ chỉnh, chẳng hạn như luồng RAW.
  • Cần có trình tự chụp ảnh tương tác.
Phiên bản API được hỗ trợ Tiện ích Camera2: Android 13 trở lên
Tiện ích CameraX: camera-extensions 1.1.0 trở lên
Tiện ích Camera2: Android 12L trở lên
Tiện ích CameraX: camera-extensions 1.2.0-alpha03 trở lên

Luồng ứng dụng

Bảng sau đây cho thấy 3 loại luồng ứng dụng và các lệnh gọi API Tiện ích máy ảnh tương ứng. Mặc dù Camera2/X cung cấp các API này, nhưng bạn phải triển khai đúng cách thư viện của nhà cung cấp để hỗ trợ các luồng này. Chúng tôi sẽ mô tả chi tiết hơn trong phần sau.

Tiện ích Camera2 Tiện ích CameraX
Khả năng sử dụng phần mở rộng truy vấn CameraExtensionCharacteristics .getSupportedExtensions ExtensionsManager. isExtensionAvailable
Thông tin truy vấn CameraExtensionCharacteristics. getExtensionSupportedSizes CameraExtensionCharacteristics. getEstimatedCaptureLatencyRangeMillis CameraExtensionCharacteristics. getAvailableCaptureRequestKeys CameraExtensionCharacteristics. getAvailableCaptureResultKeys ExtensionsManager. getEstimatedCaptureLatencyRange

CameraX xử lý phần thông tin còn lại trong thư viện.

Xem trước và chụp ảnh tĩnh khi bật tiện ích CameraDevice. createExtensionSession

cameraExtensionsSession. setRepeatingRequest

cameraExtensionsSession. capture

val cameraSelector = ExtensionsManager. getExtensionEnabledCameraSelector

bindToLifecycle(lifecycleOwner, cameraSelector, preview, ...)

Trình mở rộng cơ bản

Giao diện Trình mở rộng cơ bản cung cấp các móc vào một số vị trí trong quy trình máy ảnh. Mỗi loại tiện ích đều có các lớp Trình mở rộng tương ứng mà nhà sản xuất thiết bị gốc (OEM) cần triển khai.

Bảng sau đây liệt kê các lớp Extender mà OEM cần triển khai cho từng tiện ích:

Các lớp mở rộng để triển khai
Đêm NightPreviewExtenderImpl.java

NightImageCaptureExtenderImpl.java

HDR HdrPreviewExtenderImpl.java

HdrImageCaptureExtenderImpl.java

Tự động AutoPreviewExtenderImpl.java

AutoImageCaptureExtenderImpl.java

Bokeh BokehPreviewExtenderImpl.java

BokehImageCaptureExtenderImpl.java

Làm đẹp khuôn mặt BeautyPreviewExtenderImpl.java

BeautyImageCaptureExtenderImpl.java

Chúng ta sử dụng PreviewExtenderImplImageCaptureExtenderImpl làm phần giữ chỗ trong ví dụ sau. Thay thế các tên này bằng tên của các tệp thực tế mà bạn đang triển khai.

Trình mở rộng cơ bản có các chức năng sau:

  • Chèn các tham số phiên khi định cấu hình CameraCaptureSession ( onPresetSession).
  • Thông báo cho bạn về các sự kiện bắt đầu và kết thúc phiên chụp, đồng thời gửi một yêu cầu duy nhất để thông báo cho HAL bằng các tham số được trả về (onEnableSession, onDisableSession).
  • Chèn các tham số chụp cho yêu cầu (PreviewExtenderImpl.getCaptureStage, ImageCaptureExtenderImpl.getCaptureStages).
  • Thêm trình xử lý để xem trước và vẫn có thể chụp ảnh có khả năng xử lý luồng YUV_420_888.

Hãy xem cách Camera2/X gọi extensions-interface để đạt được 3 luồng ứng dụng nêu trên.

Quy trình 1 của ứng dụng: Kiểm tra khả năng sử dụng tiện ích

BasicExtenderAppFlow1

Hình 3. Luồng ứng dụng 1 trên Trình mở rộng cơ bản

Trong luồng này, Camera2/X gọi trực tiếp phương thức isExtensionAvailable() của cả PreviewExtenderImplImageCaptureExtenderImpl mà không cần gọi init(). Cả hai lớp Extender đều phải trả về true để bật các tiện ích.

Đây thường là bước đầu tiên để các ứng dụng kiểm tra xem loại tiện ích nhất định có được hỗ trợ cho một mã máy ảnh nhất định hay không trước khi bật tiện ích. Điều này là do một số tiện ích chỉ được hỗ trợ trên một số mã máy ảnh nhất định.

Luồng ứng dụng 2: Truy vấn thông tin

BasicExtenderAppFlow2

Hình 4. Quy trình ứng dụng 2 trên Trình mở rộng cơ bản

Sau khi xác định xem phần mở rộng có sẵn hay không, ứng dụng sẽ truy vấn thông tin sau trước khi bật phần mở rộng.

  • Dải độ trễ chụp ảnh tĩnh: ImageCaptureExtenderImpl.getEstimatedCaptureLatencyRange trả về dải độ trễ chụp ảnh để ứng dụng đánh giá xem có nên bật tiện ích cho trường hợp hiện tại hay không.

  • Kích thước được hỗ trợ cho nền tảng xem trước và chụp: ImageCaptureExtenderImpl.getSupportedResolutionsPreviewExtenderImpl.getSupportedResolutions trả về danh sách các định dạng hình ảnh và kích thước được hỗ trợ cho định dạng và kích thước nền tảng.

  • Các khoá yêu cầu và kết quả được hỗ trợ: Camera2/X gọi các phương thức sau để truy xuất khoá yêu cầu chụp và khoá kết quả được hỗ trợ từ quá trình triển khai của bạn:

    • ImageCaptureExtenderImpl.getAvailableCaptureRequestKeys
    • ImageCaptureExtenderImpl.getAvailableCapturetResultKeys

Camera2/X luôn gọi init() trước tiên trên các lớp Extender này trước khi truy vấn để biết thêm thông tin.

Quy trình ứng dụng 3: Xem trước/chụp ảnh tĩnh khi bật tiện ích (triển khai HAL)

BasicExtenderAppFlow3

Hình 5. Quy trình ứng dụng 3 trên Trình mở rộng cơ bản

Sơ đồ trên minh hoạ quy trình chính để bật tính năng xem trước và chụp ảnh tĩnh bằng một tiện ích không có bộ xử lý nào. Điều này có nghĩa là HAL máy ảnh sẽ xử lý tiện ích.

Trong luồng này, trước tiên, Camera2/X gọi init(), sau đó là onInit để thông báo cho bạn rằng một phiên máy ảnh sắp bắt đầu với các tiện ích đã chỉ định. Bạn có thể thực hiện quá trình khởi chạy nặng trong onInit().

Khi định cấu hình CameraCaptureSession, Camera2/X sẽ gọi onPresetSession để lấy các tham số phiên. Sau khi phiên chụp được định cấu hình thành công, Camera2/X sẽ gọi onEnableSession để trả về một thực thể CaptureStageImpl chứa các tham số chụp. Camera2/X sẽ ngay lập tức gửi một yêu cầu duy nhất với các tham số chụp này để thông báo cho HAL. Tương tự, trước khi phiên chụp đóng, Camera2/X sẽ gọi onDisableSession, sau đó gửi một yêu cầu duy nhất với các tham số chụp được trả về.

Yêu cầu lặp lại do Camera2/X kích hoạt chứa các tham số yêu cầu do PreviewExtenderImpl.getCaptureStage() trả về. Hơn nữa, yêu cầu chụp ảnh tĩnh chứa các tham số do ImageCaptureExtenderImpl.getCaptureStages() trả về.

Cuối cùng, Camera2/X gọi onDeInit() sau khi phiên máy ảnh kết thúc. Bạn có thể giải phóng tài nguyên trong onDeinit().

Trình xử lý xem trước

Ngoài HAL máy ảnh, bạn cũng có thể triển khai các tiện ích trong bộ xử lý.

Triển khai PreviewExtenderImpl.getProcessorType để chỉ định loại bộ xử lý như giải thích bên dưới:

  • PROCESSOR_TYPE_NONE: Không có bộ xử lý. Hình ảnh được xử lý trong HAL của máy ảnh.

  • PROCESSOR_TYPE_REQUEST_UPDATE_ONLY: Loại bộ xử lý cho phép bạn cập nhật yêu cầu lặp lại bằng các tham số yêu cầu chụp mới dựa trên TotalCaptureResult mới nhất.

    PreviewExtenderImpl.getProcessor phải trả về một thực thể RequestUpdateProcessorImpl xử lý thực thể TotalCaptureResult và trả về một thực thể CaptureStageImpl để cập nhật yêu cầu định kỳ. PreviewExtenderImpl.getCaptureStage() cũng phải phản ánh kết quả của quá trình xử lý và trả về CaptureStageImpl mới nhất.

  • PROCESSOR_TYPE_IMAGE_PROCESSOR: Loại này cho phép bạn triển khai một trình xử lý để xử lý hình ảnh YUV_420_888 và ghi đầu ra vào một nền tảng PRIVATE.

    Bạn cần triển khai và trả về một thực thể PreviewImageProcessorImpl trong PreviewExtenderImpl.getProcessor. Bộ xử lý chịu trách nhiệm xử lý hình ảnh đầu vào YUV_420_888. Hàm này sẽ ghi kết quả vào định dạng xem trước PRIVATE. Camera2/X sử dụng nền tảng YUV_420_888 thay vì PRIVATE để định cấu hình CameraCaptureSession cho bản xem trước.

    Hãy xem hình minh hoạ sau đây về quy trình:

PreviewProcessor

Hình 6. Xem trước luồng bằng PreviewImageProcessorImpl

Giao diện PreviewImageProcessorImpl mở rộng ProcessImpl và có ba phương thức quan trọng:

  • onOutputSurface(Surface surface, int imageFormat) đặt bề mặt đầu ra cho bộ xử lý. Đối với PreviewImageProcessorImpl, imageFormat là một định dạng pixel như PixelFormat.RGBA_8888.

  • onResolutionUpdate(Size size) đặt kích thước của hình ảnh đầu vào.

  • onImageFormatUpdate(int imageFormat) đặt định dạng hình ảnh của hình ảnh đầu vào. Hiện tại, bạn chỉ có thể sử dụng YUV_420_888.

Bộ xử lý chụp ảnh

Để chụp ảnh tĩnh, bạn có thể triển khai một bộ xử lý bằng cách trả về một thực thể CaptureProcessorImpl bằng ImageCaptureExtenderImpl.getCaptureProcessor. Bộ xử lý chịu trách nhiệm xử lý danh sách các bản sao hình ảnh YUV_420_888 và thực thể TotalCaptureResult đã chụp, đồng thời ghi kết quả vào một nền tảng YUV_420_888.

Bạn có thể giả định rằng bản xem trước đã được bật và đang chạy trước khi gửi yêu cầu chụp ảnh tĩnh.

Xem quy trình trong sơ đồ dưới đây:

CaptureProcessor

Hình 7. Vẫn chụp luồng bằng CaptureProcessorImpl

  1. Camera2/X sử dụng nền tảng định dạng YUV_420_888 để chụp ảnh tĩnh nhằm định cấu hình phiên chụp. Camera2/X chuẩn bị CaptureProcessorImpl bằng cách gọi:

    • CaptureProcessorImpl.onImageFormatUpdate() với YUV_420_888.
    • CaptureProcessorImpl.onResolutionUpdate() có kích thước hình ảnh đầu vào.
    • CaptureProcessorImpl.onOutputSurface() với bề mặt đầu ra YUV_420_888.
  2. ImageCaptureExtenderImpl.getCaptureStages trả về danh sách CaptureStageImpl, trong đó mỗi phần tử liên kết đến một thực thể CaptureRequest có các tham số chụp do Camera2/X gửi. Ví dụ: nếu trả về danh sách gồm 3 thực thể CaptureStageImpl, thì Camera2/X sẽ gửi 3 yêu cầu chụp có các tham số chụp tương ứng bằng API captureBurst.

  3. Các hình ảnh đã nhận và thực thể TotalCaptureResult được đóng gói với nhau và gửi đến CaptureProcessorImpl để xử lý.

  4. CaptureProcessorImpl ghi Hình ảnh kết quả (định dạng YUV_420_888) vào bề mặt đầu ra do lệnh gọi onOutputSurface() chỉ định. Camera2/X sẽ chuyển đổi hình ảnh này thành hình ảnh JPEG nếu cần.

Hỗ trợ khoá và kết quả yêu cầu chụp

Ngoài tính năng xem trước và chụp ảnh của máy ảnh, ứng dụng có thể thiết lập tính năng thu phóng, các thông số của đèn flash hoặc kích hoạt tính năng nhấn để lấy nét. Các tham số này có thể không tương thích với cách triển khai tiện ích của bạn.

Các phương thức sau đã được thêm vào extensions-interface 1.3.0 để cho phép bạn hiển thị các tham số mà phương thức triển khai của bạn hỗ trợ:

  • ImageCaptureExtenderImpl.getAvailableCaptureRequestKeys() trả về các khoá yêu cầu chụp được hỗ trợ trong quá trình triển khai.
  • ImageCaptureExtenderImpl.getAvailableCaptureResultKeys() trả về các khoá kết quả chụp có trong kết quả chụp.

Nếu HAL máy ảnh xử lý tiện ích, Camera2/X sẽ truy xuất kết quả chụp trong CameraCaptureSession.CaptureCallback. Tuy nhiên, nếu bạn triển khai trình xử lý, thì Camera2/X sẽ truy xuất kết quả chụp trong ProcessResultImpl. Kết quả này được truyền đến phương thức process() trong PreviewImageProcessorImplCaptureProcessorImpl. Bạn có trách nhiệm báo cáo kết quả chụp thông qua ProcessResultImpl cho Camera2/X.

Hãy xem định nghĩa của giao diện CaptureProcessorImpl dưới đây làm ví dụ. Trong extensions-interface 1.3.0 trở lên, lệnh gọi process() thứ hai được gọi:

Interface CaptureProcessorImpl extends ProcessorImpl {
    // invoked when extensions-interface version < 1.3.0
    void process(Map<Integer, Pair<Image, TotalCaptureResult>> results);
    // invoked when extensions-interface version >= 1.3.0
    void process(Map<Integer, Pair<Image, TotalCaptureResult>> results,
            ProcessResultImpl resultCallback, Executor executor);
}

Đối với các thao tác phổ biến trên máy ảnh như thu phóng, nhấn để lấy nét, đèn flash và bù phơi sáng, bạn nên hỗ trợ các phím sau đây cho cả yêu cầu chụp và kết quả chụp:

  • Thu phóng:
    • CaptureRequest#CONTROL_ZOOM_RATIO
    • CaptureRequest#SCALER_CROP_REGION
  • Nhấn để lấy nét:
    • CaptureRequest#CONTROL_AF_MODE
    • CaptureRequest#CONTROL_AF_TRIGGER
    • CaptureRequest#CONTROL_AF_REGIONS
    • CaptureRequest#CONTROL_AE_REGIONS
    • CaptureRequest#CONTROL_AWB_REGIONS
  • Flash:
    • CaptureRequest#CONTROL_AE_MODE
    • CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER
    • CaptureRequest#FLASH_MODE
  • Bù phơi sáng:
    • CaptureRequest#CONTROL_AE_EXPOSURE_COMPENSATION

Đối với Trình mở rộng cơ bản triển khai phiên bản 1.2.0 trở về trước, API Tiện ích CameraX hỗ trợ rõ ràng tất cả các khoá ở trên. Đối với extensions-interface 1.3.0, cả CameraX và Camera2 đều tuân theo danh sách được trả về và chỉ hỗ trợ các khoá có trong danh sách đó. Ví dụ: nếu bạn quyết định chỉ trả về CaptureRequest#CONTROL_ZOOM_RATIOCaptureRequest#SCALER_CROP_REGION trong quá trình triển khai phiên bản 1.3.0, thì điều đó có nghĩa là ứng dụng chỉ hỗ trợ tính năng thu phóng trong khi không cho phép tính năng nhấn để lấy nét, đèn flash và bù phơi sáng.

Trình mở rộng nâng cao

Trình mở rộng nâng cao là một loại phương thức triển khai của nhà cung cấp dựa trên API Camera2. Loại Trình mở rộng này được thêm vào extensions-interface 1.2.0. Tuỳ thuộc vào nhà sản xuất thiết bị, các tiện ích có thể được triển khai trong lớp ứng dụng, tuỳ thuộc vào các yếu tố sau:

  • Cấu hình luồng tuỳ chỉnh: Định cấu hình luồng tuỳ chỉnh như luồng RAW hoặc có nhiều luồng cho nhiều mã máy ảnh thực.

  • Khả năng gửi yêu cầu Camera2: Hỗ trợ logic tương tác phức tạp có thể gửi yêu cầu chụp ảnh bằng các tham số dựa trên kết quả của các yêu cầu trước đó.

Trình mở rộng nâng cao cung cấp một trình bao bọc hoặc lớp trung gian để bạn có thể tùy chỉnh cấu hình luồng và gửi yêu cầu chụp theo yêu cầu.

Các tệp cần triển khai

Để chuyển sang triển khai Trình mở rộng nâng cao, phương thức isAdvancedExtenderImplemented() trong ExtensionVersionImpl phải trả về true. Đối với mỗi loại tiện ích, nhà sản xuất thiết bị gốc phải triển khai các lớp Tiện ích tương ứng. Các tệp triển khai Trình mở rộng nâng cao nằm trong gói nâng cao.

Các lớp mở rộng để triển khai
Đêm advanced/NightAdvancedExtenderImpl.java
HDR advanced/HdrAdvancedExtenderImpl.java
Tự động advanced/AutoAdvancedExtenderImpl.java
Bokeh advanced/BokehAdvancedExtenderImpl.java
Làm đẹp khuôn mặt advanced/BeautyAdvancedExtenderImpl.java

Chúng ta sử dụng AdvancedExtenderImpl làm phần giữ chỗ trong ví dụ sau. Thay thế tên này bằng tên của tệp Trình mở rộng cho tiện ích bạn đang triển khai.

Hãy xem cách Camera2/X gọi extensions-interface để thực hiện 3 luồng ứng dụng.

Quy trình ứng dụng 1: Kiểm tra phạm vi cung cấp của tiện ích

AdvancedAppFlow1

Hình 8. Quy trình ứng dụng 1 trên Trình mở rộng nâng cao

Trước tiên, ứng dụng sẽ kiểm tra xem phần mở rộng đã cho có được hỗ trợ hay không.

Luồng ứng dụng 2: Truy vấn thông tin

AdvancedAppFlow2

Hình 9. Quy trình ứng dụng 2 trên Trình mở rộng nâng cao

Sau khi gọi AdvancedExtenderImpl.init(), ứng dụng có thể truy vấn thông tin sau trên AdvancedExtenderImpl:

  • Độ trễ chụp ảnh tĩnh ước tính: AdvancedExtenderImpl.getEstimatedCaptureLatencyRange() trả về phạm vi độ trễ chụp để ứng dụng đánh giá xem có nên bật tiện ích cho trường hợp hiện tại hay không.

  • Các độ phân giải được hỗ trợ để xem trước và chụp ảnh tĩnh:

    • AdvancedExtenderImpl.getSupportedPreviewOutputResolutions() trả về một bản đồ định dạng hình ảnh đến danh sách kích thước được hỗ trợ cho định dạng và kích thước nền tảng xem trước. Nhà sản xuất thiết bị gốc (OEM) phải hỗ trợ ít nhất định dạng PRIVATE.

    • AdvancedExtenderImpl.getSupportedCaptureOutputResolutions() trả về định dạng và kích thước được hỗ trợ cho nền tảng chụp ảnh tĩnh. Nhà sản xuất thiết bị gốc phải hỗ trợ cả đầu ra định dạng JPEGYUV_420_888.

    • AdvancedExtenderImpl.getSupportedYuvAnalysisResolutions() trả về các kích thước được hỗ trợ cho một luồng YUV_420_888 bổ sung để phân tích hình ảnh. Nếu không hỗ trợ bề mặt YUV phân tích hình ảnh, getSupportedYuvAnalysisResolutions() sẽ trả về null hoặc danh sách trống.

  • Các khoá/kết quả yêu cầu chụp có sẵn (được thêm vào extensions-interface 1.3.0): Camera2/X gọi các phương thức sau để truy xuất khoá yêu cầu chụp và khoá kết quả được hỗ trợ từ quá trình triển khai của bạn:

    • AdvancedExtenderImpl.getAvailableCaptureRequestKeys
    • AdvancedExtenderImpl.getAvailableCaptureResultKeys

Để biết thêm thông tin, hãy xem phần Hỗ trợ khoá và kết quả yêu cầu chụp.

Quy trình ứng dụng 3: Xem trước/chụp ảnh tĩnh khi bật tiện ích

AdvancedAppFlow3

Hình 10. Quy trình ứng dụng 3 trên Trình mở rộng nâng cao

Sơ đồ trên cho thấy quy trình chính để bắt đầu xem trước và chụp ảnh tĩnh cho loại Trình mở rộng nâng cao. Hãy cùng xem từng bước.

  1. Phiên bản SessionProcessorImpl

    Việc triển khai Trình mở rộng nâng cao cốt lõi nằm trong SessionProcessorImpl. Thành phần này chịu trách nhiệm cung cấp cấu hình phiên tuỳ chỉnh và gửi yêu cầu chụp để bắt đầu xem trước và vẫn chụp yêu cầu. AdvancedExtenderImpl.createSessionProcessor() được gọi để trả về thực thể SessionProcessorImpl.

  2. initSession

    SessionProcessorImpl.initSession() khởi chạy phiên cho tiện ích. Đây là nơi bạn phân bổ tài nguyên và trả về cấu hình phiên để chuẩn bị CameraCaptureSession.

    Đối với các tham số đầu vào, Camera2/X chỉ định cấu hình bề mặt đầu ra để xem trước, chụp ảnh tĩnh và phân tích hình ảnh YUV (không bắt buộc). Cấu hình bề mặt đầu ra này (OutputSurfaceImpl) chứa bề mặt, kích thước và định dạng hình ảnh được truy xuất bằng các phương thức sau trong AdvancedExtenderImpl:

    • getSupportedPreviewOutputResolutions()
    • getSupportedCaptureOutputResolutions()
    • getSupportedYuvAnalysisResolutions()

    Bạn phải trả về một thực thể Camera2SessionConfigImpl, bao gồm danh sách các thực thể Camera2OutputConfigImpl và các thông số phiên dùng để định cấu hình CameraCaptureSession. Bạn chịu trách nhiệm xuất hình ảnh máy ảnh chính xác đến các nền tảng đầu ra do Camera2/X truyền vào. Sau đây là một số tuỳ chọn để bật đầu ra:

    • Xử lý trong HAL máy ảnh: Bạn có thể trực tiếp thêm các nền tảng đầu ra vào CameraCaptureSession bằng cách triển khai SurfaceOutputConfigImpl. Thao tác này sẽ định cấu hình bề mặt đầu ra được cung cấp cho quy trình máy ảnh và cho phép HAL máy ảnh xử lý hình ảnh.
    • Xử lý nền tảng ImageReader trung gian (RAW, YUV, v.v.): Thêm các nền tảng ImageReader trung gian vào CameraCaptureSession bằng một thực thể ImageReaderOutputConfigImpl.

      Bạn cần xử lý hình ảnh trung gian và ghi hình ảnh kết quả vào bề mặt đầu ra.

    • Sử dụng tính năng chia sẻ giao diện Camera2: Sử dụng tính năng chia sẻ giao diện với một giao diện khác bằng cách thêm bất kỳ thực thể Camera2OutputConfigImpl nào vào phương thức getSurfaceSharingOutputConfigs() của một thực thể Camera2OutputConfigImpl khác. Định dạng và kích thước của nền tảng phải giống nhau.

    Tất cả Camera2OutputConfigImpl bao gồm SurfaceOutputConfigImplImageReaderOutputConfigImpl phải có mã nhận dạng duy nhất (getId()). Mã này dùng để chỉ định bề mặt mục tiêu và truy xuất hình ảnh từ ImageReaderOutputConfigImpl.

  3. onCaptureSessionStartRequestProcessorImpl

    Khi CameraCaptureSession khởi động và khung Máy ảnh gọi onConfigured(), thì Camera2/X sẽ gọi SessionProcessorImpl.onCaptureSessionStart() bằng trình bao bọc yêu cầu Camera2 RequestProcessImpl. Camera2/X triển khai RequestProcessImpl, cho phép bạn thực thi các yêu cầu chụptruy xuất hình ảnh nếu sử dụng ImageReaderOutputConfigImpl.

    Các API RequestProcessImpl tương tự như các API Camera2 CameraCaptureSession về cách thực thi yêu cầu. Điểm khác biệt là:

    • Bề mặt mục tiêu được chỉ định bằng mã nhận dạng của thực thể Camera2OutputConfigImpl.
    • Khả năng truy xuất hình ảnh của ImageReader.

    Bạn có thể gọi RequestProcessorImpl.setImageProcessor() bằng một mã nhận dạng Camera2OutputConfigImpl được chỉ định để đăng ký một thực thể ImageProcessorImpl nhằm nhận hình ảnh.

    Thực thể RequestProcessImpl sẽ không hợp lệ sau khi Camera2/X gọi SessionProcessorImpl.onCaptureSessionEnd().

  4. Bắt đầu bản xem trước và chụp ảnh

    Trong quá trình triển khai Trình mở rộng nâng cao, bạn có thể gửi yêu cầu chụp thông qua giao diện RequestProcessorImpl. Camera2/X sẽ thông báo cho bạn về việc bắt đầu yêu cầu lặp lại để xem trước hoặc trình tự chụp ảnh tĩnh bằng cách gọi lần lượt SessionProcessorImpl#startRepeatingSessionProcessorImpl#startCapture. Bạn nên gửi yêu cầu chụp để đáp ứng các yêu cầu xem trước và chụp ảnh tĩnh này.

    Camera2/X cũng đặt các tham số yêu cầu chụp thông qua SessionProcessorImpl#setParameters. Bạn phải đặt các tham số yêu cầu này (nếu tham số được hỗ trợ) trên cả yêu cầu lặp lại và yêu cầu đơn lẻ.

    Bạn phải hỗ trợ ít nhất CaptureRequest.JPEG_ORIENTATIONCaptureRequest.JPEG_QUALITY. extensions-interface 1.3.0 hỗ trợ khoá yêu cầu và khoá kết quả được hiển thị bằng các phương thức sau:

    • AdvancedExtenderImpl.getAvailableCaptureRequestKeys()
    • AdvancedExtenderImpl.getAvailableCaptureResultKeys()

    Khi nhà phát triển đặt các khoá trong danh sách getAvailableCaptureRequestKeys, bạn phải bật các tham số và đảm bảo kết quả chụp chứa các khoá trong danh sách getAvailableCaptureResultKeys.

  5. startTrigger

    SessionProcessorImpl.startTrigger() được gọi để bắt đầu điều kiện kích hoạt như CaptureRequest.CONTROL_AF_TRIGGERCaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER. Bạn có thể bỏ qua mọi khoá yêu cầu chụp không được quảng cáo trong AdvancedExtenderImpl.getAvailableCaptureRequestKeys().

    startTrigger() được hỗ trợ kể từ extensions-interface 1.3.0. API này cho phép các ứng dụng triển khai tính năng nhấn để lấy nét và đèn flash bằng các tiện ích.

  6. Dọn dẹp

    Khi kết thúc một phiên chụp, SessionProcessorImpl.onCaptureSessionEnd() sẽ được gọi trước khi đóng CameraCaptureSession. Sau khi phiên chụp ảnh kết thúc, deInitSession() sẽ thực hiện việc dọn dẹp.

Hỗ trợ xem trước, chụp ảnh tĩnh và phân tích hình ảnh

Bạn nên áp dụng tiện ích này cho cả trường hợp sử dụng xem trước và chụp ảnh tĩnh. Tuy nhiên, nếu độ trễ quá cao để hiển thị bản xem trước một cách mượt mà, bạn có thể chỉ áp dụng tiện ích này cho tính năng chụp ảnh tĩnh.

Đối với loại Trình mở rộng cơ bản, bất kể có bật phần mở rộng để xem trước hay không, bạn phải triển khai cả ImageCaptureExtenderImplPreviewExtenderImpl cho một phần mở rộng nhất định. Thông thường, ứng dụng cũng sử dụng luồng YUV để phân tích nội dung hình ảnh, chẳng hạn như tìm mã QR hoặc văn bản. Để hỗ trợ tốt hơn cho trường hợp sử dụng này, bạn nên hỗ trợ chế độ kết hợp luồng xem trước, chụp ảnh tĩnh và luồng YUV_420_888 để định cấu hình CameraCaptureSession. Điều này có nghĩa là nếu triển khai một trình xử lý, bạn phải hỗ trợ tổ hợp luồng gồm ba luồng YUV_420_888.

Đối với Trình mở rộng nâng cao, Camera2/X sẽ truyền ba nền tảng đầu ra đến lệnh gọi SessionProcessorImpl.initSession(). Các nền tảng đầu ra này lần lượt dùng để xem trước, chụp ảnh tĩnh và phân tích hình ảnh. Bạn phải đảm bảo rằng bản xem trước và các nền tảng đầu ra vẫn chụp được cho thấy kết quả hợp lệ. Tuy nhiên, đối với giao diện đầu ra phân tích hình ảnh, hãy đảm bảo giao diện này chỉ hoạt động khi không có giá trị rỗng. Nếu cách triển khai của bạn không thể hỗ trợ luồng phân tích hình ảnh, bạn có thể trả về một danh sách trống trong AdvancedExtenderImpl.getSupportedYuvAnalysisResolutions(). Điều này đảm bảo rằng giao diện đầu ra của quá trình phân tích hình ảnh luôn rỗng trong SessionProcessorImpl.initSession().

Hỗ trợ quay video

Cấu trúc Tiện ích máy ảnh hiện tại chỉ hỗ trợ các trường hợp sử dụng xem trước và chụp ảnh tĩnh. Chúng tôi không hỗ trợ bật tiện ích trên nền tảng MediaCodec hoặc MediaRecorder để quay video. Tuy nhiên, ứng dụng có thể ghi lại đầu ra xem trước.

Chúng tôi đang điều tra việc hỗ trợ các nền tảng MediaCodecMediaRecorder.

Siêu dữ liệu dành riêng cho tiện ích

Đối với Android 14 trở lên, siêu dữ liệu dành riêng cho tiện ích cho phép ứng dụng tiện ích máy ảnh thiết lập và nhận các chế độ cài đặt và kết quả yêu cầu chụp dành riêng cho tiện ích. Cụ thể, ứng dụng tiện ích máy ảnh có thể sử dụng tham số yêu cầu chụp EXTENSION_STRENGTH để kiểm soát cường độ tiện ích và kết quả chụp EXTENSION_CURRENT_TYPE để cho biết loại tiện ích đã bật.

Ghi lại yêu cầu

Tham số yêu cầu chụp EXTENSION_STRENGTH kiểm soát độ mạnh của hiệu ứng xử lý hậu kỳ của tiện ích. Kết quả chụp tương ứng bao gồm giá trị cường độ mặc định nếu ứng dụng không đặt tham số này một cách rõ ràng. Bạn có thể áp dụng tham số này như sau cho các loại tiện ích sau:

  • BOKEH: Kiểm soát mức độ mờ.
  • HDRNIGHT: Kiểm soát số lượng hình ảnh được hợp nhất và độ sáng của hình ảnh cuối cùng.
  • FACE_RETOUCH: Kiểm soát mức độ cải thiện mỹ phẩm và làm mịn da.

Phạm vi được hỗ trợ cho tham số EXTENSION_STRENGTH là từ 0 đến 100, trong đó 0 cho biết không có quá trình xử lý tiện ích hoặc truyền đơn giản và 100 cho biết cường độ tiện ích tối đa của hiệu ứng xử lý.

Để thêm tính năng hỗ trợ cho EXTENSION_STRENGTH, hãy sử dụng các API tham số dành riêng cho nhà cung cấp được giới thiệu trong phiên bản 1.3.0 của giao diện thư viện tiện ích. Để biết thêm thông tin, hãy xem getAvailableCaptureRequestKeys().

Ghi lại kết quả

Kết quả chụp EXTENSION_CURRENT_TYPE cho phép các hoạt động triển khai tiện ích thông báo cho ứng dụng về loại tiện ích đang hoạt động.

Vì các tiện ích sử dụng loại AUTO tự động chuyển đổi giữa các loại tiện ích như HDRNIGHT tuỳ thuộc vào điều kiện cảnh, nên các ứng dụng tiện ích máy ảnh có thể sử dụng EXTENSION_CURRENT_TYPE để hiển thị thông tin về tiện ích hiện tại do tiện ích AUTO chọn.

Ước tính độ trễ chụp ảnh tĩnh theo thời gian thực

Đối với Android 14 trở lên, ứng dụng tiện ích máy ảnh có thể truy vấn thông tin ước tính về độ trễ chụp ảnh tĩnh theo thời gian thực dựa trên cảnh và điều kiện môi trường bằng cách sử dụng getRealtimeStillCaptureLatency(). Phương thức này cung cấp thông tin ước tính chính xác hơn so với phương thức getEstimatedCaptureLatencyRangeMillis() tĩnh. Dựa trên độ trễ ước tính, ứng dụng có thể quyết định bỏ qua quá trình xử lý tiện ích hoặc hiển thị một chỉ báo để thông báo cho người dùng về một thao tác chạy trong thời gian dài.

CameraExtensionSession.StillCaptureLatency latency;

latency = extensionSession.getRealtimeStillCaptureLatency();

// The capture latency from ExtensionCaptureCallback#onCaptureStarted() until ExtensionCaptureCallback#onCaptureProcessStarted().

latency.getCaptureLatency();

// The processing latency from  ExtensionCaptureCallback#onCaptureProcessStarted() until  the processed frame returns to the client.

latency.getProcessingLatency();

Để hỗ trợ tính năng ước tính độ trễ chụp ảnh tĩnh theo thời gian thực, hãy triển khai các bước sau:

Ghi lại các lệnh gọi lại tiến trình xử lý

Đối với Android 14 trở lên, ứng dụng tiện ích máy ảnh có thể nhận lệnh gọi lại cho tiến trình của các thao tác xử lý ảnh tĩnh chạy trong thời gian dài. Ứng dụng có thể hiển thị tiến trình hiện tại cho người dùng để cải thiện trải nghiệm tổng thể của người dùng.

Các ứng dụng có thể sử dụng mã sau để tích hợp tính năng này:

import android.hardware.camera2.CameraExtensionSession.
ExtensionCaptureCallback;

{
…
  class AppCallbackImpl extends ExtensionCaptureCallback {
…
    @Override
    public void onCaptureProcessProgressed(
      @NonNull CameraExtensionSession session,
      @NonNull CaptureRequest request,
      @IntRange(from = 0, to = 100) int progress) {
      // Update app UI with current progress
    }
  }
…
}

Để hỗ trợ lệnh gọi lại tiến trình xử lý ảnh chụp, quá trình triển khai của nhà cung cấp tiện ích phải gọi các lệnh gọi lại sau đây với giá trị tiến trình hiện tại:

Chụp ảnh tĩnh sau khi xem

Đối với Android 14 trở lên, tiện ích máy ảnh có thể cung cấp chế độ xem sau (hình ảnh xem trước) bằng cách sử dụng setPostviewOutputConfiguration. Để cải thiện trải nghiệm người dùng, ứng dụng có thể hiển thị hình ảnh sau khi xem dưới dạng phần giữ chỗ khi một tiện ích đang gặp phải độ trễ xử lý tăng lên và thay thế hình ảnh đó khi có hình ảnh cuối cùng. Ứng dụng có thể định cấu hình và đưa ra yêu cầu chụp sau khi xem bằng mã tham chiếu sau:

{
…
if (!CameraExtensionCharacteristics.isPostviewAvailable()) {
    continue;
}
…
ExtensionSessionConfiguration extensionConfiguration = new
        ExtensionSessionConfiguration(
                CameraExtensionCharacteristics.EXTENSION_NIGHT,
                outputConfig,
                backgroundExecutor,
                extensionSessionStateCallback
    );

extensionConfiguration.setPostviewOutputConfiguration(
    postviewImageOutput);
…
CaptureRequest.Builder captureRequestBuilder =
    cameraDevice.createCaptureRequest(
        CameraDevice.TEMPLATE_STILL_CAPTURE);
captureRequestBuilder.addTarget(stillImageReader.getSurface());
captureRequestBuilder.addTarget(postviewImageSurface);

CaptureRequest captureRequest = captureRequestBuilder.build();
…
}

Để hỗ trợ tính năng chụp ảnh tĩnh sau khi xem, nhà cung cấp triển khai phải triển khai những nội dung sau:

Hỗ trợ đầu ra SurfaceView

Đối với Android 14 trở lên, ứng dụng tiện ích máy ảnh có thể sử dụng các đường dẫn kết xuất bản xem trước được tối ưu hoá về hiệu suất và năng lượng bằng cách đăng ký một thực thể SurfaceView cho đầu ra bản xem trước cho các yêu cầu lặp lại.

Để hỗ trợ đầu ra SurfaceView, quá trình triển khai tiện ích của nhà cung cấp phải có khả năng truyền trực tuyến và xuất bản xem trước sang các thực thể SurfaceView. Để xác minh rằng tính năng này được hỗ trợ, hãy chạy mô-đun CTS SurfaceViewExtensionPreviewTest.java.

Các loại phiên dành riêng cho nhà cung cấp

Tính năng này cho phép triển khai tiện ích của nhà cung cấp để chọn loại phiên dành riêng cho nhà cung cấp sẽ được đặt trong phiên chụp ảnh bằng máy ảnh nội bộ thay vì giá trị mặc định.

Tính năng này hoạt động hoàn toàn trong khung và ngăn xếp nhà cung cấp, đồng thời không ảnh hưởng đến API hiển thị công khai/ứng dụng.

Để chọn loại phiên dành riêng cho nhà cung cấp, hãy triển khai những nội dung sau cho thư viện tiện ích: * ExtenderStateListener.onSessionType() đối với tiện ích cơ bản * Camera2SessionConfigImpl.getSessionType() đối với tiện ích nâng cao

Nhật ký phiên bản giao diện tiện ích

Bảng sau đây cho thấy nhật ký phiên bản giao diện Tiện ích máy ảnh. Bạn nên luôn triển khai thư viện nhà cung cấp bằng phiên bản mới nhất.

Phiên bản Tính năng bổ sung
1.0.0
  • Xác minh phiên bản
    • ExtensionVersionImpl
  • Trình mở rộng cơ bản
    • PreviewExtenderImpl
    • ImageCaptureExtenderImpl
    • Processor
      • PreviewImageProcessorImpl
      • CaptureProcessorImpl
      • RequestUpdateProcessorImpl
1.1.0
  • Khởi động thư viện
    • InitializerImpl
  • Hiển thị độ phân giải được hỗ trợ
    • PreviewExtenderImpl.getSupportedResolutions
    • ImageCaptureExtenderImpl.getSupportedResolutions
1.2.0
  • AdvancedExtender
    • AdvancedExtenderImpl
    • SessionProcessorImpl
  • Nhận độ trễ chụp ảnh ước tính
    • ImageCaptureExtenderImpl.getEstimatedCaptureLatencyRange
1.3.0
  • Hiển thị các khoá yêu cầu chụp/khoá kết quả được hỗ trợ
    • ImageCaptureExtenderImpl.getAvailableCaptureRequestKeysgetAvailableCaptureResultKeys
    • AdvancedExtenderImpl.getAvailableCaptureRequestKeysgetAvailableCaptureResultKeys
    • Lệnh gọi process() mới lấy ProcessResultImpl trong PreviewImageProcessorImplCaptureProcessorImpl
    • Yêu cầu hỗ trợ loại trình kích hoạt
      • AdvancedExtenderImpl.startTrigger
1.4.0
  • Siêu dữ liệu dành riêng cho tiện ích
  • Ước tính độ trễ chụp ảnh tĩnh động
  • Ghi lại các lệnh gọi lại tiến trình xử lý
  • Chụp ảnh tĩnh sau khi xem
  • Hỗ trợ đầu ra SurfaceView
  • Các loại phiên dành riêng cho nhà cung cấp

Triển khai tham chiếu

Các cách triển khai thư viện nhà cung cấp OEM tham chiếu sau đây có trong frameworks/ex.

  • advancedSample: Cách triển khai cơ bản của Trình mở rộng nâng cao.

  • sample: Cách triển khai cơ bản của Trình mở rộng cơ bản.

  • service_based_sample: Cách triển khai minh hoạ cách lưu trữ Tiện ích máy ảnh trong Service. Phương thức triển khai này chứa các thành phần sau:

    • oem_library: Thư viện OEM của Tiện ích máy ảnh cho API Tiện ích Camera2 và CameraX triển khai Extensions-Interface. Đây là một phương thức truyền tải chuyển tiếp các lệnh gọi từ Extensions-Interface đến dịch vụ. Thư viện này cũng cung cấp các tệp AIDL và lớp trình bao bọc để giao tiếp với dịch vụ.

      Trình mở rộng nâng cao được bật theo mặc định. Để bật Trình mở rộng cơ bản, hãy thay đổi ExtensionsVersionImpl#isAdvancedExtenderImplemented để trả về false.

    • extensions_service: Một cách triển khai mẫu của Dịch vụ tiện ích. Thêm cách triển khai của bạn vào đây. Giao diện để triển khai trong dịch vụ tương tự như Extensions-Interface. Ví dụ: việc triển khai IAdvancedExtenderImpl.Stub sẽ thực hiện các thao tác giống như AdvancedExtenderImpl. Bạn bắt buộc phải sử dụng ImageWrapperTotalCaptureResultWrapper để tạo ImageTotalCaptureResult có thể phân phối.

Thiết lập thư viện nhà cung cấp trên thiết bị

Thư viện nhà cung cấp OEM không được tích hợp vào ứng dụng; thư viện này được Camera2/X tải từ thiết bị trong thời gian chạy. Trong CameraX, thẻ <uses-library> khai báo rằng thư viện androidx.camera.extensions.impl (được xác định trong tệp AndroidManifest.xml của thư viện camera-extensions) là phần phụ thuộc của CameraX và phải được tải trong thời gian chạy. Trong Camera2, khung này sẽ tải một dịch vụ tiện ích cũng khai báo rằng <uses-library> sẽ tải cùng một thư viện androidx.camera.extensions.impl trong thời gian chạy.

Điều này cho phép các ứng dụng bên thứ ba sử dụng tiện ích để tự động tải thư viện nhà cung cấp OEM. Thư viện OEM được đánh dấu là không bắt buộc để ứng dụng có thể chạy trên các thiết bị không có thư viện trên thiết bị. Camera2/X tự động xử lý hành vi này khi một ứng dụng cố gắng sử dụng tiện ích máy ảnh, miễn là nhà sản xuất thiết bị đặt thư viện OEM trên thiết bị để ứng dụng có thể phát hiện được.

Để thiết lập thư viện OEM trên một thiết bị, hãy làm như sau:

  1. Thêm tệp quyền mà thẻ <uses-library> yêu cầu, bằng định dạng sau: /etc/permissions/ANY_FILENAME.xml. Ví dụ: /etc/permissions/camera_extensions.xml. Các tệp trong thư mục này cung cấp thông tin ánh xạ thư viện có tên trong <uses-library> đến đường dẫn tệp thực tế trên thiết bị.
  2. Hãy sử dụng ví dụ bên dưới để thêm thông tin bắt buộc vào tệp.

    • name phải là androidx.camera.extensions.impl vì đó là thư viện mà CameraX tìm kiếm.
    • file là đường dẫn tuyệt đối của tệp chứa quá trình triển khai tiện ích (ví dụ: /system/framework/androidx.camera.extensions.impl.jar).
    <?xml version="1.0" encoding="utf-8"?>
    <permissions>
        <library name="androidx.camera.extensions.impl"
                 file="OEM_IMPLEMENTED_JAR" />
    </permissions>
    

Trong Android 12 trở lên, các thiết bị hỗ trợ tiện ích CameraX phải đặt thuộc tính ro.camerax.extensions.enabled thành true. Thao tác này cho phép truy vấn xem thiết bị có hỗ trợ tiện ích hay không. Để thực hiện việc này, hãy thêm dòng sau vào tệp tạo thiết bị:

PRODUCT_VENDOR_PROPERTIES += \
    ro.camerax.extensions.enabled=true \

Xác nhận kết quả

Để kiểm thử việc triển khai thư viện nhà cung cấp OEM trong giai đoạn phát triển, hãy sử dụng ứng dụng mẫu tại androidx-main/camera/integration-tests/extensionstestapp/. Ứng dụng này chạy thông qua nhiều tiện ích của nhà cung cấp.

Sau khi hoàn tất quá trình triển khai, hãy sử dụng công cụ xác thực tiện ích máy ảnh để chạy các bài kiểm thử tự động và thủ công nhằm xác minh rằng thư viện nhà cung cấp được triển khai chính xác.

Chế độ cảnh mở rộng so với tiện ích máy ảnh

Đối với tiện ích bokeh, ngoài việc hiển thị tiện ích này bằng tiện ích máy ảnh, bạn còn có thể hiển thị tiện ích này bằng chế độ cảnh mở rộng. Chế độ này được bật thông qua khoá CONTROL_EXTENDED_SCENE_MODE. Để biết thêm thông tin chi tiết về cách triển khai, hãy xem phần Hiệu ứng bokeh của máy ảnh.

Chế độ cảnh mở rộng có ít hạn chế hơn so với các tiện ích máy ảnh cho ứng dụng camera2. Ví dụ: bạn có thể bật chế độ cảnh mở rộng trong một thực thể CameraCaptureSession thông thường hỗ trợ các tổ hợp luồng linh hoạt và các tham số yêu cầu chụp. Ngược lại, tiện ích máy ảnh chỉ hỗ trợ một nhóm cố định các loại luồng và có hỗ trợ hạn chế đối với các tham số yêu cầu chụp.

Nhược điểm của chế độ cảnh mở rộng là bạn chỉ có thể triển khai chế độ này trong HAL máy ảnh, tức là chế độ này phải được xác minh để hoạt động trên tất cả các chế độ điều khiển vuông góc mà nhà phát triển ứng dụng có thể sử dụng.

Bạn nên sử dụng cả chế độ cảnh mở rộng và Tiện ích máy ảnh để chụp ảnh bokeh vì các ứng dụng có thể muốn sử dụng một API cụ thể để bật hiệu ứng bokeh. Trước tiên, bạn nên sử dụng chế độ cảnh mở rộng vì đây là cách linh hoạt nhất để các ứng dụng bật tiện ích hiệu ứng bokeh. Sau đó, bạn có thể triển khai giao diện tiện ích máy ảnh dựa trên chế độ cảnh mở rộng. Ví dụ: nếu việc triển khai hiệu ứng bokeh trong HAL máy ảnh gặp khó khăn, chẳng hạn như vì cần có bộ xử lý hậu kỳ chạy trong lớp ứng dụng để xử lý hình ảnh, thì bạn nên triển khai tiện ích bokeh bằng giao diện Tiện ích máy ảnh.

Câu hỏi thường gặp

Có giới hạn nào đối với cấp độ API không?

Có. Điều này phụ thuộc vào bộ tính năng API Android mà nhà sản xuất thiết bị gốc (OEM) yêu cầu khi triển khai thư viện nhà cung cấp. Ví dụ: ExtenderStateListener.onPresetSession() sử dụng lệnh gọi SessionConfiguration.setSessionParameters() để đặt một nhóm thẻ cơ sở. Lệnh gọi này chỉ có trên API cấp 28 trở lên. Để biết thông tin chi tiết về các phương thức giao diện cụ thể, hãy xem tài liệu tham khảo API.