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

Android 10 เปิดตัว API การจัดการบัฟเฟอร์HAL3 ของกล้องที่ไม่บังคับ ซึ่งช่วยให้คุณใช้ตรรกะการจัดการบัฟเฟอร์เพื่อแลกกับการลดเวลาในการตอบสนองของหน่วยความจำและการจับภาพได้

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

การจัดการบัฟเฟอร์ในเวอร์ชัน 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 ของกล้องสามารถใช้กลยุทธ์ที่แตกต่างกันสำหรับ Use Case บางรายการ เช่น ใช้กลยุทธ์การประหยัดหน่วยความจำสูงสุดสำหรับ Use Case ที่ใช้หน่วยความจำมาก และใช้กลยุทธ์ที่เข้ากันได้แบบย้อนหลังสำหรับ Use Case อื่นๆ

ตัวอย่างการใช้งานใน HAL ของกล้องภายนอก

HAL ของกล้องภายนอกเปิดตัวใน Android 9 และดูได้ในต้นไม้ซอร์สโค้ดที่ hardware/interfaces/camera/device/3.5/ ใน Android 10 มีการอัปเดตเพื่อรวม ExternalCameraDeviceSession.cpp ซึ่งเป็นการใช้งาน API การจัดการบัฟเฟอร์ HAL ของกล้องภายนอกนี้ใช้กลยุทธ์การประหยัดหน่วยความจำสูงสุดที่กล่าวถึงในกลยุทธ์การจัดการบัฟเฟอร์ในโค้ด C++ ไม่กี่ร้อยบรรทัด