Commit 2d8a6d23 authored by Hake Huang's avatar Hake Huang Committed by Chris Friedt
Browse files

tests: display: support headless mode

for test machine without display, need support open-cv-headless mode.

1. support headless mode
2. add parser for environment path

Signed-off-by: default avatarHake Huang <hake.huang@oss.nxp.com>
parent 1d6da406
Loading
Loading
Loading
Loading
+36 −3
Changes for scripts/pylib/display-twister-harness/camera_shield/main.py: 36 added lines, 3 removed lines.
Original line number Diff line number Diff line
@@ -24,13 +24,13 @@ class Application:
            """Process yaml with Template strings for safer environment variable resolution."""
            if isinstance(yaml_dict, dict):
                return {k: resolve_env_vars(v) for k, v in yaml_dict.items()}
            elif isinstance(yaml_dict, list):
            if isinstance(yaml_dict, list):
                return [resolve_env_vars(i) for i in yaml_dict]
            elif isinstance(yaml_dict, str):
            if isinstance(yaml_dict, str):
                # Create a template and substitute environment variables
                template = Template(yaml_dict)
                return template.safe_substitute(os.environ)
            else:

            return yaml_dict

        self.active_plugins = {}  # Initialize empty plugin dictionary
@@ -93,15 +93,48 @@ class Application:
                    continue

                # Maintain OpenCV event loop
                try:
                    if cv2.waitKey(1) == 27:  # ESC key
                        break
                except Exception as e:
                    error_msg = str(e).lower()
                    if any(
                        phrase in error_msg
                        for phrase in [
                            "not implemented",
                            "rebuild the library",
                            "gtk",
                            "cocoa support",
                        ]
                    ):
                        # Expected error in headless environment - continue
                        pass
                    else:
                        print(f"Error during waitKey: {e}")

                results = {}
                for name, plugin in self.active_plugins.items():
                    results[name] = plugin.process_frame(frame)

                self.handle_results(results, frame)
                try:
                    self.camera.show_frame(frame)
                except Exception as e:
                    error_msg = str(e).lower()
                    if any(
                        phrase in error_msg
                        for phrase in [
                            "not implemented",
                            "rebuild the library",
                            "gtk",
                            "cocoa support",
                        ]
                    ):
                        # Expected error in headless environment - continue
                        pass
                    else:
                        print(f"Error during show_frame: {e}")

                frame_delay = 1 / self.case_config["fps"]
                if time.time() - start_time > self.case_config["run_time"]:
                    break
+10 −1
Changes for scripts/pylib/display-twister-harness/camera_shield/uvc_core/camera_controller.py: 10 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -168,7 +168,7 @@ class UVCCamera:
        print(f"  Color Balance - B Channel: {analysis['color_balance']['b_channel']:.2f}")
        print(f"  Sharpness: {analysis['sharpness']:.2f}")

        # 在帧上显示分析结果
        # show report
        if frame is not None:
            text_y = 30
            cv2.putText(
@@ -269,4 +269,13 @@ class UVCCamera:

    def release(self):
        self.cap.release()
        try:
            # compatible with openCV-headless mode
            cv2.destroyAllWindows()
        except Exception as e:
            # Handle cv2.error and other potential exceptions
            if "not implemented" in str(e) or "Rebuild the library" in str(e):
                # This is expected in headless/no-GUI environments
                pass
            else:
                print(f"Warning: Could not destroy windows: {e}")
+4 −1
Changes for scripts/pylib/twister/twisterlib/harness.py: 4 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@ import time
import xml.etree.ElementTree as ET
from collections import OrderedDict
from enum import Enum
from string import Template

import junitparser.junitparser as junit
import yaml
@@ -647,7 +648,9 @@ class Display_capture(Pytest):

    def _get_display_config_file(self, harness_config):
        if test_config_file := harness_config.get('display_capture_config'):
            test_config_path = os.path.join(self.source_dir, test_config_file)
            _template = Template(test_config_file)
            _config_file = _template.safe_substitute(os.environ)
            test_config_path = os.path.join(self.source_dir, _config_file)
            logger.info(f'test_config_path = {test_config_path}')
            if os.path.exists(test_config_path):
                return test_config_path