Android 10 ขอแนะนำ API การจัดการบัฟเฟอร์สำหรับ กล้องถ่ายรูป HAL3 ที่ไม่บังคับ ซึ่งจะช่วยให้คุณใช้ตรรกะการจัดการบัฟเฟอร์ได้เพื่อให้ได้หน่วยความจำที่ต่างกันและลดเวลาในการตอบสนองของเวลาในการตอบสนองในการใช้งาน HAL ของกล้อง
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 การจัดการบัฟเฟอร์
เมื่อใช้ Buffer Management API เพื่อใช้ตรรกะการจัดการบัฟเฟอร์ ให้พิจารณาถึงการเปลี่ยนแปลงลักษณะการทำงานที่อาจเกิดขึ้นกับกล้องและการใช้งาน HAL ของกล้อง ดังนี้
คำขอจับภาพมาถึง HAL ของกล้องเร็วขึ้นและบ่อยขึ้น: หากไม่มี API การจัดการบัฟเฟอร์ เฟรมเวิร์กกล้องจะขอบัฟเฟอร์เอาต์พุตสำหรับคำขอจับภาพแต่ละรายการก่อนที่จะส่งคำขอจับภาพไปยัง HAL ของกล้อง เมื่อใช้ Buffer Management 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 ของกล้องสามารถใช้กลยุทธ์ต่างๆ กับกรณีการใช้งานเฉพาะ เช่น การใช้กลยุทธ์การประหยัดหน่วยความจำสูงสุดสำหรับกรณีการใช้งานที่ใช้หน่วยความจำมาก และการใช้กลยุทธ์ที่เข้ากันได้แบบย้อนหลังสำหรับกรณีการใช้งานอื่นๆ
ตัวอย่างการใช้งานใน HAL ของกล้องภายนอก
HAL ของกล้องภายนอกเปิดตัวใน Android 9 และดูได้ในต้นไม้ซอร์สโค้ดที่ hardware/interfaces/camera/device/3.5/
ใน Android 10 มีการอัปเดตเพื่อรวม ExternalCameraDeviceSession.cpp
ซึ่งเป็นการใช้งาน API การจัดการบัฟเฟอร์ HAL ของกล้องภายนอกนี้ใช้กลยุทธ์การประหยัดหน่วยความจำสูงสุดซึ่งได้กล่าวถึงในกลยุทธ์การจัดการบัฟเฟอร์ในโค้ด C++ ไม่กี่ร้อยบรรทัด