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