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

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

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

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

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

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

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

หากต้องการใช้ API การจัดการบัฟเฟอร์ กล้อง HAL จะต้อง:

กล้อง 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++ สองสามร้อยบรรทัด