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

Android 10 ขอแนะนำ API การจัดการบัฟเฟอร์สำหรับ กล้องถ่ายรูป 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 ของกล้อง

การจัดการบัฟเฟอร์ในเวอร์ชัน 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 การจัดการบัฟเฟอร์

เมื่อใช้ Buffer Management API เพื่อใช้ตรรกะการจัดการบัฟเฟอร์ ให้พิจารณาถึงการเปลี่ยนแปลงลักษณะการทำงานที่อาจเกิดขึ้นกับกล้องและการใช้งาน HAL ของกล้อง ดังนี้

  • คำขอจับภาพมาถึง HAL ของกล้องเร็วขึ้นและบ่อยขึ้น: หากไม่มี API การจัดการบัฟเฟอร์ เฟรมเวิร์กกล้องจะขอบัฟเฟอร์เอาต์พุตสำหรับคำขอจับภาพแต่ละรายการก่อนที่จะส่งคำขอจับภาพไปยัง HAL ของกล้อง เมื่อใช้ Buffer Management 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++ ไม่กี่ร้อยบรรทัด