มุมมองกล้อง HAR

หน่วยงานกำกับดูแลของรัฐบาลได้กำหนดข้อกำหนดหลายประการเพื่อให้แน่ใจว่า การมองเห็นด้านหลังโดยอ้อมให้ข้อมูลเพียงพอในการบังคับควบคุมยานพาหนะอย่างแม่นยำ และทันท่วงที ซึ่งส่งผลต่อการรับรู้สภาพแวดล้อมของคนขับ

สำหรับระบบการมองเห็นด้านหลังที่อิงตามระบบตรวจสอบด้วยกล้อง (CMS) หน่วยงานความปลอดภัยการจราจรทางหลวงแห่งชาติ (NHTSA) กำหนดให้คุณต้องปฏิบัติตามข้อกำหนดเหล่านี้ (S6.6.2.3 อ้างอิงจาก UNECE46)

  • S5.5.3 เวลาตอบสนอง รูปภาพจากกระจกมองหลังที่เป็นไปตามข้อกำหนดของ S5.5.1 (ขอบเขตการมองเห็น) และ S5.5.2 (ขนาด) เมื่อทดสอบตาม S14.2 จะแสดงภายใน 2.0 วินาทีหลังจากเริ่มเหตุการณ์ถอยหลัง

  • S5.5.4 เวลาที่ใช้ในร้าน รูปภาพจากกล้องมองหลังที่เป็นไปตามข้อกำหนดของ S5.5.1 และ S5.5.2 จะไม่แสดงหลังจากเหตุการณ์การถอยสิ้นสุดลง

  • S5.5.5 การปิดใช้งาน ภาพจากกระจกมองหลังที่ตรงตามข้อกำหนดของ S5.5.1 และ S5.5.2 จะยังคงปรากฏในระหว่างเหตุการณ์ถอยหลังจนกว่าผู้ขับจะ แก้ไขมุมมอง หรือตัวเลือกทิศทางของรถจะเปลี่ยนจากตำแหน่งถอยหลัง

  • S6.6.2.3.3.5 อาร์ติแฟกต์ คู่มือการใช้งานของผู้ปฏิบัติงานควรระบุถึงอาร์ติแฟกต์ที่อาจเกิดขึ้น และผลกระทบต่อการบดบังบางส่วนของขอบเขตการมองเห็น และของออบเจ็กต์ ซึ่งอาจทำให้ผู้ขับขี่ต้องตื่นตัว และใส่ใจเป็นพิเศษ

  • S6.2.2.3.4.1 อัตราเฟรม การเคลื่อนไหวของวัตถุที่อยู่หน้ากล้อง จะแสดงผลได้อย่างราบรื่น อัตราเฟรมขั้นต่ำของระบบคืออย่างน้อย 30 Hz (เทียบเท่ากับ 30 FPS) ในสภาพแสงน้อยหรือขณะเลี้ยว ที่ความเร็วต่ำ อัตราเฟรมขั้นต่ำของระบบจะอยู่ที่ 15 Hz เป็นอย่างน้อย

  • S6.2.2.3.4.2 เวลาในการสร้างภาพ เวลาในการสร้างภาพของจอภาพน้อยกว่า 55 มิลลิวินาทีที่อุณหภูมิ 22 องศาเซลเซียส ± 5 องศาเซลเซียส

  • S6.2.2.3.4.3 เวลาในการตอบสนองของระบบ ระบบจอภาพของกล้อง (CMS) มีเวลาในการตอบสนองที่สั้นเพียงพอที่จะแสดงทิวทัศน์ในเวลาเดียวกัน เวลาในการตอบสนองต่ำกว่า 200 มิลลิวินาทีที่อุณหภูมิ 22 องศาเซลเซียส ± 5 องศาเซลเซียส

เราได้เปิดตัว Extended View System (EVS) ของ Android Automotive OS (AAOS) เพื่อให้เป็นไปตามข้อกำหนดเหล่านี้ใน AAOS ที่ไม่มีการปรับแต่ง เราได้เปิดตัวบริการที่คล้ายกันสำหรับระบบเสมือนจริงในอุปกรณ์ AAOS ที่มีตัวแสดงผลที่มีความพร้อมใช้งานสูง (HAR) ซึ่งแสดงให้เห็นถึงการปฏิบัติตามข้อกำหนดเหล่านี้ด้วย

ไปป์ไลน์การแสดงตัวอย่างจากกล้อง

5 ขั้นตอนนี้ประกอบกันเป็นไปป์ไลน์การแสดงตัวอย่างจากกล้อง

ขั้นตอนไปป์ไลน์การแสดงตัวอย่างจากกล้อง

รูปที่ 1 ขั้นตอนของไปป์ไลน์การแสดงตัวอย่างจากกล้อง

การบล็อกบริการกล้องหมายถึงแพลตฟอร์มบริการกล้องและเลเยอร์การแยกข้อมูล ที่ช่วยให้แอปเข้าถึงและใช้กล้องที่พร้อมใช้งานได้ ฟังก์ชัน Display Service จะแสดงข้อมูลภาพต่อผู้ใช้ แอปจะใช้เส้นทางของผู้ใช้เป้าหมาย กับบริการกล้องและบริการแสดงผล

เส้นทางของผู้ใช้หลักในการมองเห็นด้านหลังมีดังนี้

  1. ผู้ขับขี่วางตัวเลือกทิศทาง (เกียร์) ในตำแหน่งถอยหลังเพื่อทริกเกอร์ เหตุการณ์ถอยหลัง

  2. ระบบจะออกอากาศกิจกรรมที่อยู่เบื้องหลัง แอปจะได้รับการออกอากาศและ เริ่มต้นบล็อกข้อมูลจากกล้อง (บริการกล้อง) และตัวแสดงผล (บริการแสดงผล)

  3. บล็อกอินพุตของกล้องจะเริ่มต้นแพลตฟอร์มบริการกล้องและส่งคืนแฮนเดิลบริการไปยังแอป

  4. ตัวแสดงผลจะเริ่มต้นหน้าต่างมุมมองสำหรับข้อมูลจากกล้องจากขั้นตอนที่ 4

  5. แอปขอให้บล็อกอินพุตของกล้องเริ่มส่งบัฟเฟอร์เฟรมและ เหตุการณ์

  6. แอปจะจัดคิวบัฟเฟอร์เฟรมที่ส่งผ่านการเรียกกลับ (แบบอะซิงโครนัส) บล็อกอินพุตของกล้องเป็นเจ้าของบัฟเฟอร์เฟรม ดังนั้นแอปจึงแก้ไขบัฟเฟอร์เฟรมไม่ได้

  7. แอปจะนำบัฟเฟอร์เฟรมออกจากคิว (หากคิวไม่ว่าง) และสร้างมุมมองของผู้ใช้ ผู้ใช้สามารถทำสำเนาเพื่อแก้ไขเนื้อหาได้

  8. แอปส่งบัฟเฟอร์ไปยังโปรแกรมแสดงผล

  9. ตัวแสดงผลจะวาดเนื้อหาของบัฟเฟอร์ที่ได้รับบนจอแสดงผล

  10. หากเหตุการณ์ที่สำรองข้อมูลยังคงดำเนินการอยู่ ให้ไปที่ขั้นตอนที่ 7 เมื่อเหตุการณ์การสำรองข้อมูลเสร็จสมบูรณ์ แอปจะขอให้บล็อกอินพุตของกล้องหยุดส่งบัฟเฟอร์เฟรมและเหตุการณ์หลังจากซ่อนมุมมองจากผู้ใช้

  11. แอปจะปิดกล้องและปล่อยตัวแสดงผลหรือไม่ก็ได้

รูปที่ 1 แสดงขั้นตอน รูปภาพนี้ใช้องค์ประกอบจาก API ของไลบรารี QNX Camera เพื่อใช้แพลตฟอร์มบริการกล้อง

เส้นทางของผู้ใช้หลักของ HAR

รูปที่ 2 เส้นทางของผู้ใช้หลักของ HAR

บล็อกข้อมูลจากกล้องประกาศอินเทอร์เฟซ 3 รายการ ได้แก่

  • CameraManager ประกาศเมธอดเพื่อจัดการอุปกรณ์กล้อง เช่น แอปใช้อินเทอร์เฟซนี้เพื่อเปิด (จอง) อุปกรณ์กล้องเป้าหมาย

  • CameraDevice ประกาศเมธอดเพื่อควบคุมอุปกรณ์กล้อง เช่น การเริ่มหรือหยุดสตรีมข้อมูล

  • CameraStreamListener ประกาศเมธอดเดียวเพื่อรับเหตุการณ์ต่างๆ จากกล้องเป้าหมาย

การออกแบบ

ส่วนนี้จะอธิบายรายละเอียดการออกแบบระบบ

ประสบการณ์ของผู้ใช้

คนขับสามารถดูตัวอย่างกล้องหลังบนจอแสดงผลแผงหน้าปัดได้เมื่อ เข้าเกียร์ถอย จอแสดงผลจะหยุดแสดงตัวอย่างกล้องเมื่อ ผู้ขับขี่เปลี่ยนเกียร์จากถอยหลัง

คุณเปิดใช้เส้นทางของผู้ใช้เพิ่มเติมได้ เช่น ผู้ขับสามารถดูตัวอย่าง พื้นที่ที่มองไม่เห็นในกระจกเมื่อเปิดสัญญาณไฟเลี้ยว

เริ่มการแสดงตัวอย่างจากกล้อง

เมื่อใช้กล้อง แอปจะแสดงรายการและประเมินกล้องที่มีอยู่เพื่อค้นหากล้องที่ดีที่สุดสำหรับวัตถุประสงค์ที่ต้องการ ตัวอย่างเช่น สำหรับทัศนวิสัยด้านหลัง แอปจะค้นหากล้องที่แสดงด้านหลังของยานพาหนะจากรายการกล้องที่พร้อมใช้งาน

แอปจะประเมินโดยการตรวจสอบลักษณะของกล้องแต่ละตัว เช่น ตำแหน่ง ทิศทางของเลนส์ อัตราเฟรม ความละเอียดเอาต์พุต และรูปแบบ เอาต์พุต หากกล้องหลายตัวมีลักษณะที่จำเป็นเหมือนกัน แอปอาจตรวจสอบลักษณะเพิ่มเติม เช่น มุมมองและระยะโฟกัส

รูปภาพนี้แสดงลำดับการเริ่มต้นตัวอย่างกล้องที่มีการกำหนดค่ากล้องแบบคงที่

เริ่มแสดงตัวอย่างกล้องด้วยการกำหนดค่ากล้องแบบคงที่

รูปที่ 3 เริ่มแสดงตัวอย่างกล้องด้วยการกำหนดค่ากล้องแบบคงที่

หยุดการแสดงตัวอย่างจากกล้อง

แอปจะหยุดแสดงภาพด้านหลังเมื่อเหตุการณ์การถอยสิ้นสุดลง เพื่อไม่ให้แสดงหน้าจอว่างหรือภาพนิ่ง แอปจะซ่อนมุมมองจากผู้ใช้ก่อน แล้วจึงขอให้บล็อกข้อมูลจากกล้องหยุดส่งเหตุการณ์

รูปภาพนี้แสดงลำดับการหยุดสตรีมข้อมูลจากกล้องเป้าหมาย อุปกรณ์

หยุดสตรีมข้อมูลจากอุปกรณ์กล้องเป้าหมาย

รูปที่ 4 หยุดสตรีมข้อมูลจากอุปกรณ์กล้องเป้าหมาย

ข้อผิดพลาด

อุปกรณ์กล้องอาจหยุดส่งบัฟเฟอร์เฟรมใหม่โดยไม่คาดคิด หากต้องการตรวจจับเหตุการณ์ดังกล่าว บล็อกอินพุตของกล้องอาจใช้ตัวจับเวลาที่จะหมดเวลาเมื่อเฟรมใหม่มาถึง และส่งการแจ้งเตือนเมื่อตัวจับเวลาหมดเวลา

เมื่อแอปได้รับการแจ้งเตือน แอปจะแจ้งให้ผู้ใช้ทราบว่าตัวอย่างกล้อง ไม่ได้แสดงภาพสดอีกต่อไป และพยายามกู้คืนตัวอย่างกล้องโดยการปิด อุปกรณ์กล้องแล้วเปิดอีกครั้ง รูปที่ 5 แสดงวิธีที่แอปจัดการการหมดเวลา

การจัดการระยะหมดเวลา

รูปที่ 5 การจัดการการหมดเวลา (สตรีมข้อมูลค้าง)

ข้อมูลจากกล้องสามารถรายงานเหตุการณ์อื่นๆ นอกเหนือจากสตรีมข้อมูลที่ค้างอยู่ และฝังรายละเอียดเพิ่มเติมในบัฟเฟอร์ OEM สามารถใช้ข้อมูลเมตาของเหตุการณ์นี้เพื่อจัดการ เหตุการณ์ในแพลตฟอร์มของตนได้

กิจกรรม

แอปที่ทำงานบนโฮสต์และจัดการจอแสดงผลแผงหน้าปัดจะใช้ API ผ่าน HAR (บล็อกสีน้ำเงินในแผนภาพด้านล่าง)

แผนภาพระบบแสดงในรูปที่ 5

แผนภาพระบบ

รูปที่ 6 แผนภาพระบบ

บริการ

คาดว่าการเรียก API จะทำงานในบริบทของกระบวนการเรียก

API

API ใหม่นี้มีไว้สำหรับแอปที่จัดการตัวอย่างกล้องบนจอแสดงผลแผงหน้าปัดผ่าน HAR เท่านั้น API พร้อมใช้งานผ่านเลเยอร์การแยกแพลตฟอร์มและลิงก์แบบไดนามิก

อินเทอร์เฟซ CameraInputBlock ประกาศเมธอดเพื่อเริ่มต้นฟังก์ชันการทำงานของกล้องและรับเครื่องมือจัดการบล็อกอินพุต แอปใช้อินสแตนซ์ CameraManager ที่ส่งคืนเพื่อจัดการอุปกรณ์กล้อง

// This class represents a camera input block for the application that manages the
// instrument cluster display with Harry.
public class CameraInputBlock : public InputBlock {
    public:
        // Clean up the resources.
        virtual ~CameraInputBlock();

        // A method inherited from InputBlock class. This method initializes
        // CameraInputBlock instance; e.g. checking the platform camera service
        // is live.
        //
        // @return CAMERA_EPERM if the platform camera service is not
        //                      available.
        //         CAMERA_OK otherwise.
        virtual CameraError init() override;

        // A method inherited from InputBlock class. This method release all
        // resources held by this CameraInputBlock instance.
        virtual void release() override;

        // This method returns a CameraManager instance. The caller uses
        // this instance to manage camera devices.
        //
        // @param out If this method is successful, this points to a valid
        //            CameraManager instance.
        // @return CAMERA_EACCESS when we fail to create CameraManager instance
        //         to return.
        //         CAMERA_OK otherwise.
        virtual CameraError getCameraManager(
            std::shared_ptr<CameraManager>* out) = 0;

    private:
        // Handle to manage camera devices.
        std::shared_ptr<CameraManager> mMgr;

        // Handle to manage camera devices that have been opened by clients.
        std::set<CameraDevice> mCameras;
};

คลาส CameraManager ประกาศเมธอดเพื่อเปิด (หรือเป็นเจ้าของ) กล้องและปล่อย เมื่อแอปใช้กล้องนั้นเสร็จแล้ว แอปสามารถเปิดกล้องได้มากกว่า 1 ตัวและใช้สตรีมของกล้องเหล่านั้นเพื่อสร้างมุมมองที่กว้างขึ้นหรือประสบการณ์แบบหลายมุมมอง

// This pure virtual class declares methods to manage camera devices.
public class CameraManager {
    public:
        // This method returns a list of CameraDescriptor objects representing
        // available cameras.
        //
        // @param out A list of CameraDescriptor instances. This list may be
        //            empty if the platform camera service does not list any
        //            camera.
        // @return CAMERA_EACCESS if we failed to build a camera list.
        //         CAMERA_OK otherwise.
        virtual CameraError getCameraList(
            std::vector<CameraDescriptor>* out) = 0;

        // Open a camera device associated with a given string identifier.
        //
        // @param ID A string identifier of a camera device to request.
        // @param out A pointer to CameraDevice shared pointer object. This
        //            is null when we fail to open a target device.
        // @return CAMERA_ENODEV if no camera is associated with a given id.
        //         CAMERA_EACCESS if it fails to open a target device.
        //         CAMERA_OK otherwise.
        virtual CameraError open(
            std::string ID, std::shared_ptr<CameraDevice>* out) = 0;

        // Close a camera device associated with a given string identifier.
        // This method is assumed to be always successful.
        //
        // @param id A string identifier of a camera device to close.
        virtual void close(std::string id) = 0;
};

หากแอปตรวจไม่พบว่าควรใช้กล้องใด แอปจะเลือกกล้องที่ทำงานได้ดีที่สุดในบริบทนั้น CameraManager::getCameraList() จะแสดงรายการของอินสแตนซ์ CameraDescriptor ซึ่งระบุลักษณะของกล้องแต่ละตัว

คลาส CameraDevice แสดงถึงอุปกรณ์กล้องตัวเดียวและประกาศเมธอด เพื่อเริ่มและหยุดสตรีมข้อมูล หากไม่ทราบลักษณะของกล้องแบบคงที่ ไคลเอ็นต์จะรับลักษณะดังกล่าวจากตัวอธิบายและแยกวิเคราะห์

ตัวอย่างเช่น ไคลเอ็นต์สามารถรับรายการการกำหนดค่าสตรีมที่อุปกรณ์กล้องเป้าหมาย เสนอจากข้อมูลเมตา และเลือกรายการที่มีแอตทริบิวต์ดีที่สุด (เช่น อัตราเฟรม ความละเอียด และรูปแบบเอาต์พุต)

// This class represents a single camera device.
public class CameraDevice {
    public:
        // Start a data stream that attributes are matching to given
        // configuration best.
        // If a selected configuration is not given (null), a data stream is
        // initiated in its default configuration and return.
        //
        // @param configuration Selected attributes of the imagery data stream.
        // @param listener An object to listen to an active data stream.
        // @param effective Actual attributes of started data stream.
        // @return CAMERA_EINVAL if a listener object is invalid.
        //         CAMERA_EIO if we failed to start a video stream.
        //         CAMERA_OK otherwise.
        virtual CameraError start(
                std::shared_ptr<CameraStreamConfiguration>& configuration,
                std::shared_ptr<CameraStreamListener>& listener,
                std::shared_ptr<CameraStreamConfiguration>* effective) = 0;

        // Stop a data stream.
        virtual void stop() = 0;

        // Get a camera descriptor.
        //
        // @param desc A set of attributes that defines this camera device.
        // @return CAMERA_ENODATA if a descriptor is not available.
        //         CAMERA_OK otherwise.
        CameraError getDescriptor(std::shared_ptr<CameraDescriptor>* desc) = 0;

        // Return a consumed buffer to the camera device. A client of active
        // stream must return a frame buffer explicitly by calling this method.
        virtual void doneWithFrame(std::shared_ptr<FrameBuffer>& buffer) = 0;

    private:
        // Describe this camera device.
        CameraDescriptor mDescriptor;

        // A weak reference to a listening client.
        std::weak_ptr<CameraStreamListener> mClient;
};

// This class declares attributes that characterize a camera device.
public class CameraDescriptor {
    public:
        // Unique std::string object to identify a single camera device.
        std::string mId;

        // A set of stream configurations this camera device is capable of. A
        // camera must have at least one stream configuration.
        std::set<CameraStreamConfiguration> mConfigurations;

        // Are more attributes needed to exist, such as locations, lens
        // facing directions, and intrinsic/extrinsic parameters?
};

// This class declares attributes that characterize an imagery data stream.
public class CameraStreamConfiguration {
    public:
        // Width of output of this stream in pixels.
        unsigned int mWidthInPixels;

        // Height of output of this stream in pixels.
        unsigned int mHeightInPixels;

        // An average number of frames per second.
        double mFrameRate;

        // A format of this stream's output. A client could calculate a
        // byte-per-pixel (bpp) from this.
        CameraColorFormat mFormat;
};

// This class represents a listener/callback object to listen to frames and
// events.
public class CameraStreamListener {
    public:
        // A listener method to receive various stream events including a new
        // frame buffer.
        //
        // @param event CameraStreamEvent object that represents a single event
        //              such as an arrival of a new frame buffer, camera stream
        //              is terminated, and so forth.
        virtual void onEvent(std::shared_ptr<CameraStreamEvent>* event) = 0;
};

CameraDevice::start() รับอาร์กิวเมนต์ 3 รายการ ได้แก่

  • การกำหนดค่าสตรีมที่ผู้โทรเลือก

  • Listener เพื่อรับเหตุการณ์สตรีม

  • เคล็ดลับในการกำหนดค่าสตรีมที่มีประสิทธิภาพ เราขอแนะนำอย่างยิ่งให้ ผู้โทรตรวจสอบค่านี้เพื่อจัดการบัฟเฟอร์เฟรมที่เข้ามาตามที่ต้องการ

เมื่อ CameraDevice::start() เริ่มสตรีมข้อมูลด้วยแพลตฟอร์ม Camera Service จะเก็บการอ้างอิงแบบอ่อนไปยังออบเจ็กต์ Listener ของผู้เรียกเพื่อตรวจหา การสิ้นสุดที่ไม่คาดคิดของผู้เรียก

เมื่อไคลเอ็นต์ใช้เฟรมบัฟเฟอร์เสร็จแล้ว ไคลเอ็นต์ต้องแจ้งให้อุปกรณ์กล้องทราบว่าไม่จำเป็นต้องใช้เฟรมบัฟเฟอร์อีกต่อไปโดยเรียกใช้เมธอด CameraDevice::doneWithFrame()

เมื่อสตรีมเริ่มต้น ไคลเอ็นต์จะได้รับข้อความเหตุการณ์ ข้อความที่พบบ่อยคือ เฟรมบัฟเฟอร์ใหม่ ไคลเอ็นต์จะได้รับkNewFrameBuffer event ที่มีข้อมูลภาพพร้อมกับข้อมูลเมตาของเฟรม บัฟเฟอร์ผ่านฟังก์ชัน Callback ที่ลงทะเบียนไว้ StreamEventType ประกาศประเภทเพิ่มเติมเพื่อจัดการสตรีมอื่นๆ เช่น สตรีมข้อมูลที่หยุดหรือค้าง

// This class lists events possibly occurring while a data stream is active.
enum class CameraStreamEventType {
    // A delivery of a new frame buffer.
    kNewFrameBuffer,
    // A data stream has been stopped.
    kStreamStopped,
    // No new frame buffer arrives for a while.
    kStreamHang,
    // Add more.
    ...
};

// This class represents a single instance of StreamEventType.
public class CameraStreamEvent {
    public:
        // Return a type of this event.
        //
        // @return CameraStreamEventType enum value.
        CameraStreamEventType getType() { return mType; }

        // Return a pointer to data associated with this event.
        //
        // @return A shared pointer object of the buffer that contains data for
        //         this event.
        std::shared_ptr<void> getData() { return mData; }

    private:
        // Describe a type of this event.
        CameraStreamEventType mType;

        // A pointer to the data buffer.
        std::shared_ptr<void> mData;
};

// This class inherits StreamEvent class and has additional fields to represent
// the frame buffer.
public class FrameBufferEvent : public CameraStreamEvent {
    public:
        // Return an identifier of this frame buffer.
        //
        // @return A unique integer value to identify this frame buffer.
        int getBufferID() { return mBufferID; }

        // Give access to frame buffer metadata.
        //
        // @return A shared pointer to the buffer that contains data besides
        //         the imagery data.
        std::shared_ptr<void> getMetadata() { return mMetadata; }

    private:
        // Unique integer to identify this buffer.
        int mBufferID;

        // A pointer to metadata of this frame buffer.
        std::shared_ptr<void> mMetadata;
};

ตัวอย่างนี้แสดงการใช้งานอินเทอร์เฟซ CameraInputBlock และ แอป

CameraError getCameraManager(std::shared_ptr<CameraManager>* out) {
    // During an instantiation, CameraManager will retrieve a list of camera
    // devices from the platform camera service and identify their attributes.
    *out = std::make_shared<CameraManager>();
    return CAMERA_OK;
}

// This method returns a list of CameraDescriptor objects representing available
// cameras.
CameraError CameraManager::getCameraList(std::vector<CameraDescriptor>* out) {
    if (mCameraList.size() < 1) {
        // Query a list of cameras and get their attributes.
    }
    *out = mCameraList;
    return CAMERA_OK;
}

// Open a camera device associated with a given string identifier.
CameraError CameraManager::open(std::string id, std::shared_ptr<CameraDevice>* out) {
    if (!mCameraList.contains(id)) {
        // We cannot identify any camera with a given value.
        return CAMERA_NODEV;
    }

    // During a construction, CameraDevice will obtain a handle of a target
    // camera device from the platform camera service.
    std::shared_ptr<CameraDevice> h = std::make_shared<CameraDevice>(id);
    if (!h) {
        // We fail to open a camera device.
        return CAMERA_EACCESS;
    }

    *out = h;
    return CAMERA_OK;
}

// Close a camera device associated with a given string identifier. This method
// is assumed to be always successful.
void CameraManager::close(std::string id) {
    if (!mCameraList.contains(id)) {
        // We ignore calls with unknown identifiers.
        return;
    }

    // mCameraList.remove() returns an object removed from the list.
    std::shared_ptr<CameraDevice> device = mCameraList.remove(id);

    // Ensure a device stops streaming.
    device->stop();
}

// Start a data stream that attributes are matching to given configuration
// best.
// If a selected configuration is not given (null), a data stream will be
// initiated in its default configuration and return.
CameraError CameraDevice::start(
        std::shared_ptr<CameraStreamConfiguration>& configuration,
        std::shared_ptr<CameraStreamListener>& listener,
        std::shared_ptr<CameraStreamConfiguration>* effective) {
    if (!listener) {
        return CAMERA_EINVAL;
    }

    // selectStreamConfiguration examines this camera's stream configurations
    // and returns the one closest to the selected configuration.
    CameraStreamConfiguration config = selectStreamConfiguration(configuration);

    // mDevice refers to the camera handle for the platform camera service. We
    // may need to translate CameraStreamConfiguration for the platform service.
    mDevice->configure(
        configuration.mWidth, configuration.mHeight, configuration.mFormat);

    // Start a data stream with a callback object.
    if (!mDevice->startStream(mCallback)) {
        // We failed to start a data stream.
        return CAMERA_EIO;
    }

    return CAMERA_OK;
}

// Stop a data stream.
void CameraDevice::stop() {
    if (!mDevice) {
        // Nothing to do if we don't have a valid camera handle for the
        // platform camera service.
        return;
    }

    mDevice->stopStream();
}

// Get a camera descriptor.
CameraError CameraDevice::getDescriptor(std::shared_ptr<CameraDescriptor>* desc) {
    if (!mDescriptor) {
        return CAMERA_ENODATA;
    }

    *desc = *mDescriptor;
    return CAMERA_OK;
}

// Return a consumed buffer to the camera device. A client of active stream
// must return a frame buffer explicitly by calling this method.
void CameraDevice::doneWithFrame(std::shared_ptr<FrameBuffer>& buffer) {
    if (!mBufferRecords.contains(buffer.getId())) {
        // Ignore a call with unknown frame buffer.
        return;
    }

    // Simply remove from the record.
    (void)mBufferRecords.remove(buffer.getId());
}

// This method handles gear-shift events.
void Application::handleGearShift(GearSelection selection) {
    switch (selection) {
        case GEAR_SELECTION_REVERSE:
            // Upon the reverse gear selection, we are going to start a video
            // stream and show its preview on the instrument cluster display.
            (void)startStream(mCameraInputBlock);

            // FIXME: Exact method to control the camera preview window on the
            // instrument display is to be determined.
            show(mRearVisibilityWindow);
            break;

        default:
            // Upon all other gear selection, we are going to stop a video
            // stream (if it's running) and hide the preview.
            stopStream(mCameraInputBlock);

            // FIXME: Exact method to control the camera preview window on the
            // instrument display is to be determined.
            hide(mRearVisibilityWindow);
            break;
    }
}

bool Application::startStream(std::shared_ptr<CameraInputBlock> handle) {
    return handle->start(std::bind(&Application::handleStreamCallback, this);
}

void Application::stopStream(std::shared_ptr<CameraInputBlock> handle) {
    handle->stop();
}

// This method handles a stream callback.
void Application::handleStreamCallback(StreamEvent& event) {
    switch (event.getType()) {
        case StreamEventType::kNewFrameBuffer:
            // Handle a new frame buffer. We may just enqueue it for the
            // future or forward to CameraInputBlock client.
            break;

        case StreamEventType::kStreamStopped:
            // Handle as an incident if this event is not expected.
            break;

        // More cases to be added.
    }
}

void Application::handleNewFrameBuffer(StreamEvent& event) {
    // Enqueue a new frame buffer for the further processing. A buffer
    // must be returned explicitly by calling
    // CameraDevice.doneWithFrame(FrameBuffer&) method.
}

void Application::handleStreamEvent(StreamEvent& event) {
    // Handle a received stream event except a new frame buffer's
    // arrival; e.g. a video stream is terminated unexpectedly.
}

ประสิทธิภาพ

การมองเห็นด้านหลังเป็นไปตามกฎระเบียบของรัฐบาล

ค่า กฎระเบียบ
ระยะเวลาการตอบกลับ CFR 571.111 S5.5.3
อัตราเฟรม UNECE R46 6.2.2.3.4
เวลาในการสร้างภาพ UNECE R46 6.2.2.3.4.2
เวลาในการตอบสนองของระบบ UNECE R46 6.2.2.3.4.3

ความเป็นส่วนตัว

ในส่วนของความเป็นส่วนตัว

  • API ไม่ได้กำหนดให้มีการติดตั้งใช้งานเพื่อรวบรวม บันทึก หรือจัดเก็บข้อมูลส่วนบุคคลที่ระบุตัวบุคคลนั้นได้ (PII) อย่างไรก็ตาม เนื่องจากข้อมูลภาพที่บันทึกไว้ (หรือข้อมูลเมตาที่เกี่ยวข้อง) อาจมี PII แอปที่ใช้ API จึงต้องได้รับความยินยอมอย่างชัดแจ้งจากผู้ใช้

  • ผู้ใช้ไม่สามารถควบคุมอุปกรณ์กล้องเพื่อดูตัวอย่างบนจอแสดงผลแผงหน้าปัดได้เนื่องจากกล้องมีบทบาทสำคัญด้านความปลอดภัย OEM จะได้รับ ความยินยอมจากผู้ใช้ในระหว่างการตั้งค่าหรือจากไดรเวอร์

  • API นี้ไม่รองรับไคลเอ็นต์กล้องในเบื้องหลัง ดังนั้น ตัวบ่งชี้ความเป็นส่วนตัว ซึ่งจะแจ้งให้ผู้ใช้ทราบว่าอุปกรณ์กล้องกำลังบันทึกข้อมูลจึงอยู่นอกขอบเขต