API การจัดการบัฟเฟอร์ของ Camera HAL3

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 ของกล้อง

การจัดการบัฟเฟอร์ใน Android 9 หรือต่ำกว่า

รูปที่ 1 อินเทอร์เฟซ HAL ของกล้องใน Android 9 และต่ำกว่า

การจัดการบัฟเฟอร์ใน Android 10

รูปที่ 2 อินเทอร์เฟซ HAL ของกล้องใน Android 10 ที่ใช้ API การจัดการบัฟเฟอร์

ใช้ API การจัดการบัฟเฟอร์

หากต้องการใช้ API การจัดการบัฟเฟอร์ HAL ของกล้องต้องทำดังนี้

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++ เพียงไม่กี่ร้อยบรรทัด