Android 10 เปิดตัว API การจัดการบัฟเฟอร์HAL3 ของกล้องที่ไม่บังคับ ซึ่งช่วยให้คุณใช้ตรรกะการจัดการบัฟเฟอร์เพื่อแลกกับการลดเวลาในการตอบสนองของหน่วยความจำและการจับภาพได้
HAL ของกล้องต้องใช้คําขอ N รายการ (โดยที่ N เท่ากับความลึกของไปป์ไลน์) ที่รออยู่ในไปป์ไลน์ แต่มักไม่จําเป็นต้องใช้บัฟเฟอร์เอาต์พุตชุด N รายการทั้งหมดพร้อมกัน
ตัวอย่างเช่น HAL อาจมีคําขอ 8 รายการรออยู่ในไปป์ไลน์ แต่ต้องใช้บัฟเฟอร์เอาต์พุตสําหรับคําขอ 2 รายการในระยะสุดท้ายของไปป์ไลน์เท่านั้น ในอุปกรณ์ที่ใช้ Android 9 หรือต่ำกว่า เฟรมเวิร์กกล้องจะจัดสรรบัฟเฟอร์เมื่อคิวคำขอใน HAL ดังนั้นอาจมีบัฟเฟอร์ 6 ชุดใน HAL ที่ไม่ได้ใช้งาน ใน Android 10, API การจัดการบัฟเฟอร์ HAL3 ของกล้องช่วยให้สามารถแยกบัฟเฟอร์เอาต์พุตเพื่อเพิ่มพื้นที่ว่างสำหรับบัฟเฟอร์ 6 ชุด ซึ่งอาจช่วยประหยัดหน่วยความจำได้หลายร้อยเมกะไบต์ในอุปกรณ์ระดับสูง และอาจเป็นประโยชน์ต่ออุปกรณ์ที่มีหน่วยความจำต่ำด้วย
รูปที่ 1 แสดงแผนภาพอินเทอร์เฟซ HAL ของกล้องสำหรับอุปกรณ์ที่ใช้ Android 9 หรือต่ำกว่า รูปที่ 2 แสดงอินเทอร์เฟซ HAL ของกล้องใน Android 10 ที่มีการใช้ API การจัดการบัฟเฟอร์ HAL3 ของกล้อง
รูปที่ 1 อินเทอร์เฟซ HAL ของกล้องใน Android 9 และต่ำกว่า
รูปที่ 2 อินเทอร์เฟซ HAL ของกล้องใน Android 10 โดยใช้ API การจัดการบัฟเฟอร์
ใช้ API การจัดการบัฟเฟอร์
หากต้องการใช้ API การจัดการบัฟเฟอร์ HAL ของกล้องต้องมีคุณสมบัติดังนี้
- ใช้ HIDL
ICameraDevice@3.5
- ตั้งค่าคีย์ลักษณะกล้อง
android.info.supportedBufferManagementVersion
เป็นHIDL_DEVICE_3_5
HAL ของกล้องใช้เมธอด requestStreamBuffers
และ returnStreamBuffers
ใน ICameraDeviceCallback.hal
เพื่อขอและแสดงผลบัฟเฟอร์ HAL ต้องใช้เมธอด signalStreamFlush
ใน ICameraDeviceSession.hal
เพื่อส่งสัญญาณให้ HAL ของกล้องแสดงผลบัฟเฟอร์
requestStreamBuffers
ใช้เมธอด
requestStreamBuffers
เพื่อขอบัฟเฟอร์จากเฟรมเวิร์กกล้อง เมื่อใช้ API การจัดการบัฟเฟอร์ HAL3 ของกล้อง คำขอจับภาพจากเฟรมเวิร์กกล้องจะไม่มีบัฟเฟอร์เอาต์พุต กล่าวคือ ช่อง bufferId
ใน StreamBuffer
จะเป็น 0
ดังนั้น HAL ของกล้องต้องใช้ requestStreamBuffers
เพื่อขอบัฟเฟอร์จากเฟรมเวิร์กกล้อง
เมธอด requestStreamBuffers
ช่วยให้ผู้เรียกขอบัฟเฟอร์ได้หลายรายการจากสตรีมเอาต์พุตหลายรายการในการเรียกใช้ครั้งเดียว ซึ่งทำให้การเรียกใช้ HIDL IPC น้อยลง อย่างไรก็ตาม การเรียกใช้จะใช้เวลานานขึ้นเมื่อมีการขอบัฟเฟอร์เพิ่มเติมพร้อมกัน และอาจส่งผลเสียต่อเวลาในการตอบสนองโดยรวมจากคําขอถึงผลลัพธ์
นอกจากนี้ เนื่องจากมีการเรียกใช้ requestStreamBuffers
แบบอนุกรมในบริการกล้อง เราจึงขอแนะนำให้ HAL ของกล้องใช้เธรดที่มีลําดับความสําคัญสูงโดยเฉพาะเพื่อขอบัฟเฟอร์
หากคำขอบัฟเฟอร์ไม่สำเร็จ HAL ของกล้องต้องจัดการข้อผิดพลาดที่ไม่ร้ายแรงได้อย่างถูกต้อง รายการต่อไปนี้อธิบายสาเหตุที่พบบ่อยที่ทำให้คำขอบัฟเฟอร์ไม่สำเร็จ และวิธีที่ HAL ของกล้องควรจัดการกับคำขอดังกล่าว
- แอปตัดการเชื่อมต่อจากสตรีมเอาต์พุต:
ข้อผิดพลาดนี้ไม่ร้ายแรง HAL ของกล้องควรส่ง
ERROR_REQUEST
สำหรับคำขอจับภาพที่กำหนดเป้าหมายไปยังสตรีมที่ตัดการเชื่อมต่อและพร้อมประมวลผลคำขอต่อๆ ไปตามปกติ - หมดเวลา: กรณีนี้อาจเกิดขึ้นเมื่อแอปกําลังประมวลผลอย่างหนักขณะถือบัฟเฟอร์ไว้ HAL ของกล้องควรส่ง
ERROR_REQUEST
สำหรับคำขอถ่ายภาพที่ดำเนินการไม่ได้เนื่องจากข้อผิดพลาดเกี่ยวกับเวลาหมด และพร้อมที่จะประมวลผลคำขอที่ตามมาตามปกติ - เฟรมเวิร์กกล้องกําลังเตรียมการกําหนดค่าสตรีมใหม่:
HAL ของกล้องควรรอจนกว่าการเรียกใช้
configureStreams
ครั้งถัดไปจะเสร็จสมบูรณ์ก่อนที่จะเรียกใช้requestStreamBuffers
อีกครั้ง - HAL ของกล้องมีบัฟเฟอร์ถึงขีดจำกัด (ช่อง
maxBuffers
): HAL ของกล้องควรรอจนกว่าจะได้รับบัฟเฟอร์ของสตรีมอย่างน้อย 1 รายการก่อนที่จะเรียกใช้requestStreamBuffers
อีกครั้ง
returnStreamBuffers
ใช้วิธี returnStreamBuffers
เพื่อส่งบัฟเฟอร์เพิ่มเติมกลับไปยังเฟรมเวิร์กกล้อง โดยปกติแล้ว HAL ของกล้องจะส่งบัฟเฟอร์กลับไปยังเฟรมเวิร์กกล้องผ่านเมธอด processCaptureResult
แต่สามารถจัดการกับคำขอจับภาพที่ส่งไปยัง HAL ของกล้องเท่านั้น เมื่อใช้เมธอด requestStreamBuffers
การใช้งาน HAL ของกล้องอาจเก็บบัฟเฟอร์ไว้มากกว่าที่เฟรมเวิร์กกล้องขอ กรณีนี้ควรใช้วิธีการ returnStreamBuffers
หากการใช้งาน HAL ไม่เคยเก็บบัฟเฟอร์ไว้มากกว่าที่ขอ การใช้งาน HAL ของกล้องก็ไม่จําเป็นต้องเรียกใช้returnStreamBuffers
วิธีนี้
signalStreamFlush
เฟรมเวิร์กกล้องจะเรียกใช้เมธอด signalStreamFlush
เพื่อแจ้งให้ HAL ของกล้องแสดงบัฟเฟอร์ทั้งหมดที่มี โดยปกติแล้วการเรียกใช้นี้จะดำเนินการเมื่อเฟรมเวิร์กกล้องกำลังจะเรียกใช้ configureStreams
และจะต้องล้างไปป์ไลน์การจับภาพของกล้อง เช่นเดียวกับreturnStreamBuffers
วิธีนี้ หากการใช้งาน HAL ของกล้องเก็บบัฟเฟอร์ไว้น้อยกว่าที่ขอ ก็อาจทำให้การใช้งานวิธีการนี้ว่างเปล่า
หลังจากเฟรมเวิร์กกล้องเรียกใช้ signalStreamFlush
แล้ว เฟรมเวิร์กจะหยุดส่งคำขอจับภาพใหม่ไปยัง HAL ของกล้องจนกว่าบัฟเฟอร์ทั้งหมดจะส่งกลับไปยังเฟรมเวิร์กกล้อง เมื่อระบบแสดงบัฟเฟอร์ทั้งหมดแล้ว การเรียกใช้เมธอด requestStreamBuffers
จะดำเนินการไม่สำเร็จ และเฟรมเวิร์กกล้องจะทำงานต่อไปได้ จากนั้นเฟรมเวิร์กกล้องจะเรียกใช้เมธอด configureStreams
หรือ processCaptureRequest
หากเฟรมเวิร์กกล้องเรียกใช้เมธอด configureStreams
ทาง HAL ของกล้องจะเริ่มขอบัฟเฟอร์อีกครั้งหลังจากที่การเรียกใช้ configureStreams
แสดงผลเรียบร้อยแล้ว หากเฟรมเวิร์กกล้องเรียกใช้เมธอด processCaptureRequest
ทาง HAL ของกล้องจะเริ่มขอบัฟเฟอร์ระหว่างการเรียกใช้ processCaptureRequest
ความหมายของเมธอด signalStreamFlush
กับ flush
นั้นแตกต่างกัน เมื่อเรียกใช้เมธอด flush
แล้ว HAL จะยกเลิกคำขอจับภาพที่รอดำเนินการได้โดยใช้ ERROR_REQUEST
เพื่อล้างไปป์ไลน์โดยเร็วที่สุด เมื่อเรียกใช้เมธอด signalStreamFlush
แล้ว HAL ต้องดำเนินการตามคำขอถ่ายภาพที่รอดำเนินการทั้งหมดให้เสร็จสิ้นตามปกติและส่งบัฟเฟอร์ทั้งหมดกลับไปยังเฟรมเวิร์กกล้อง
อีกความแตกต่างระหว่างเมธอด signalStreamFlush
กับเมธอดอื่นๆ คือ signalStreamFlush
เป็นเมธอด HIDL แบบทางเดียว ซึ่งหมายความว่าเฟรมเวิร์กกล้องอาจเรียก API อื่นๆ ที่บล็อกไว้ก่อนที่ HAL จะได้รับsignalStreamFlush
ซึ่งหมายความว่าวิธี signalStreamFlush
และวิธีอื่นๆ (โดยเฉพาะวิธี configureStreams
) อาจมาถึง HAL ของกล้องในลำดับที่ต่างจากลำดับที่เรียกใช้ในเฟรมเวิร์กของกล้อง ในการแก้ไขปัญหาการไม่สอดคล้องกันนี้ เราได้เพิ่มช่อง streamConfigCounter
ลงใน StreamConfiguration
และเพิ่มเป็นอาร์กิวเมนต์ในเมธอด signalStreamFlush
การใช้งาน HAL ของกล้องควรใช้อาร์กิวเมนต์ streamConfigCounter
เพื่อระบุว่าการเรียกใช้ signalStreamFlush
มาช้ากว่าการเรียกใช้ configureStreams
ที่เกี่ยวข้องหรือไม่ ดูตัวอย่างได้ที่รูปที่ 3
รูปที่ 3 วิธีที่ HAL ของกล้องควรตรวจหาและจัดการการเรียก signalStreamFlush ที่มาถึงช้า
ลักษณะการทํางานจะเปลี่ยนแปลงเมื่อติดตั้งใช้งาน API การจัดการบัฟเฟอร์
เมื่อใช้ API การจัดการบัฟเฟอร์เพื่อใช้ตรรกะการจัดการบัฟเฟอร์ ให้พิจารณาถึงการเปลี่ยนแปลงลักษณะการทำงานที่อาจเกิดขึ้นกับกล้องและการใช้งาน HAL ของกล้อง ดังนี้
คำขอจับภาพมาถึง HAL ของกล้องเร็วขึ้นและบ่อยขึ้น: หากไม่มี API การจัดการบัฟเฟอร์ เฟรมเวิร์กกล้องจะขอบัฟเฟอร์เอาต์พุตสำหรับคำขอจับภาพแต่ละรายการก่อนที่จะส่งคำขอจับภาพไปยัง HAL ของกล้อง เมื่อใช้ API การจัดการบัฟเฟอร์ เฟรมเวิร์กกล้องจะไม่ต้องรอบัฟเฟอร์อีกต่อไป จึงส่งคำขอจับภาพไปยัง HAL ของกล้องได้เร็วขึ้น
นอกจากนี้ หากไม่มี API การจัดการบัฟเฟอร์ เฟรมเวิร์กกล้องจะหยุดส่งคำขอจับภาพหากสตรีมเอาต์พุตรายการใดรายการหนึ่งของคำขอจับภาพมีบัฟเฟอร์ถึงจำนวนสูงสุดที่ HAL เก็บได้พร้อมกัน (ค่านี้กำหนดโดย HAL ของกล้องในช่อง
HalStream::maxBuffers
ในผลลัพธ์ของconfigureStreams
การเรียกใช้) เมื่อใช้ API การจัดการบัฟเฟอร์ ลักษณะการจำกัดนี้จะไม่มีอยู่อีกต่อไป และการใช้งาน HAL ของกล้องต้องไม่ยอมรับการเรียกprocessCaptureRequest
เมื่อ HAL มีคิวคำขอจับภาพมากเกินไปเวลาในการตอบสนองของสาย
requestStreamBuffers
แตกต่างกันอย่างมาก: มีสาเหตุหลายประการที่ทำให้การโทรrequestStreamBuffers
อาจใช้เวลานานกว่าค่าเฉลี่ย เช่น- การเรียกใช้อาจใช้เวลานานขึ้นสำหรับบัฟเฟอร์ 2-3 รายการแรกของสตรีมที่สร้างขึ้นใหม่ เนื่องจากอุปกรณ์ต้องจัดสรรหน่วยความจำ
- เวลาในการตอบสนองที่คาดไว้จะเพิ่มขึ้นตามสัดส่วนกับจำนวนบัฟเฟอร์ที่ขอในแต่ละการเรียกใช้
- แอปกำลังเก็บบัฟเฟอร์และประมวลผลอยู่ ซึ่งอาจทำให้คำขอบัฟเฟอร์ทำงานช้าลงหรือหมดเวลาเนื่องจากไม่มีบัฟเฟอร์หรือ CPU ทำงานอยู่
กลยุทธ์การจัดการบัฟเฟอร์
API การจัดการบัฟเฟอร์ช่วยให้ใช้กลยุทธ์การจัดการบัฟเฟอร์ประเภทต่างๆ ได้ ตัวอย่างเช่น
- เข้ากันได้แบบย้อนหลัง: HAL จะขอบัฟเฟอร์สําหรับคําขอบันทึกระหว่างการเรียกใช้
processCaptureRequest
กลยุทธ์นี้ไม่ได้ช่วยประหยัดหน่วยความจำ แต่ใช้เป็นการใช้งาน API การจัดการบัฟเฟอร์ครั้งแรกได้ ซึ่งต้องใช้การเปลี่ยนแปลงโค้ดเพียงเล็กน้อยใน HAL ของกล้องที่มีอยู่ - ประหยัดหน่วยความจำสูงสุด: HAL ของกล้องจะขอบัฟเฟอร์เอาต์พุตก็ต่อเมื่อจำเป็นต้องใช้บัฟเฟอร์เท่านั้น กลยุทธ์นี้ช่วยให้ประหยัดหน่วยความจําได้สูงสุด ข้อเสียที่อาจเกิดขึ้นคือไปป์ไลน์ของกล้องจะทำงานช้าลงเมื่อคำขอบัฟเฟอร์ใช้เวลานานผิดปกติ
- แคชไว้: HAL ของกล้องจะแคชบัฟเฟอร์ไว้ 2-3 รายการเพื่อให้มีโอกาสน้อยที่จะได้รับผลกระทบจากคำขอบัฟเฟอร์ที่ช้าเป็นครั้งคราว
HAL ของกล้องสามารถใช้กลยุทธ์ที่แตกต่างกันสำหรับ Use Case บางรายการ เช่น ใช้กลยุทธ์การประหยัดหน่วยความจำสูงสุดสำหรับ Use Case ที่ใช้หน่วยความจำมาก และใช้กลยุทธ์ที่เข้ากันได้แบบย้อนหลังสำหรับ Use Case อื่นๆ
ตัวอย่างการใช้งานใน HAL ของกล้องภายนอก
HAL ของกล้องภายนอกเปิดตัวใน Android 9 และดูได้ในต้นไม้ซอร์สโค้ดที่ hardware/interfaces/camera/device/3.5/
ใน Android 10 มีการอัปเดตเพื่อรวม ExternalCameraDeviceSession.cpp
ซึ่งเป็นการใช้งาน API การจัดการบัฟเฟอร์ HAL ของกล้องภายนอกนี้ใช้กลยุทธ์การประหยัดหน่วยความจำสูงสุดที่กล่าวถึงในกลยุทธ์การจัดการบัฟเฟอร์ในโค้ด C++ ไม่กี่ร้อยบรรทัด