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