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

Android 10 เปิดตัว API การจัดการบัฟเฟอร์ camera 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 ของกล้อง

การจัดการบัฟเฟอร์ใน 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 เพื่อขอรับบัฟเฟอร์จากเฟรมเวิร์กของกล้อง เมื่อใช้ Camera HAL3 API การจัดการบัฟเฟอร์ คำขอจับภาพจากเฟรมเวิร์กกล้องจะไม่มีบัฟเฟอร์เอาต์พุต นั่นคือฟิลด์ bufferId ใน StreamBuffer คือ 0 ดังนั้น HAL ของกล้องต้องใช้ requestStreamBuffers เพื่อขอ บัฟเฟอร์จากเฟรมเวิร์กของกล้อง

เมธอด requestStreamBuffers ช่วยให้ผู้เรียกขอหลายบัฟเฟอร์จากสตรีมเอาต์พุตหลายรายการในการเรียกครั้งเดียวได้ ซึ่งจะช่วยลดการเรียก HIDL IPC อย่างไรก็ตาม การเรียกใช้จะใช้เวลานานขึ้นเมื่อมีการขอบัฟเฟอร์หลายรายการพร้อมกัน และอาจส่งผลเสียต่อเวลาในการตอบสนองรวมตั้งแต่คำขอจนถึงผลลัพธ์ นอกจากนี้ เนื่องจากมีการจัดลำดับการเรียกใช้ใน requestStreamBuffers ในบริการกล้อง เราจึงขอแนะนำให้ HAL ของกล้องใช้เธรดที่มีลำดับความสำคัญสูงโดยเฉพาะ เพื่อขอรับบัฟเฟอร์

หากคำขอบัฟเฟอร์ไม่สำเร็จ HAL ของกล้องต้องจัดการข้อผิดพลาดที่ไม่ร้ายแรงได้อย่างถูกต้อง รายการต่อไปนี้อธิบายสาเหตุที่พบบ่อยซึ่งทำให้คำขอ buffer ล้มเหลว และวิธีที่ 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 method และวิธีอื่นๆ (โดยเฉพาะ configureStreams method) อาจไปถึง 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 มีการอัปเดตให้รวม ExternalCameraDeviceSession.cpp การใช้งาน API การจัดการบัฟเฟอร์ HAL กล้องภายนอกนี้ ใช้กลยุทธ์การประหยัดหน่วยความจำสูงสุดที่กล่าวถึงในกลยุทธ์การจัดการบัฟเฟอร์ในโค้ด C++ เพียงไม่กี่ร้อยบรรทัด