summaryrefslogtreecommitdiff
path: root/include/linux
diff options
context:
space:
mode:
authorJacopo Mondi <jacopo@jmondi.org>2020-10-02 19:22:24 +0200
committerJacopo Mondi <jacopo@jmondi.org>2020-10-07 16:07:43 +0200
commit5cf64b26a24d1430eed9523ca5899bdd3faf203b (patch)
tree1055799fd073bc7dc246d945cc4c645f9822b8c2 /include/linux
parent5fbda0dfda8dbf85022356e117fff47b184461f6 (diff)
android: camera_stream: Break out CameraStream
Break CameraStream out of the CameraDevice class. No functional changes, only the code is moved. Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
Diffstat (limited to 'include/linux')
0 files changed, 0 insertions, 0 deletions
91'>91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (C) 2024, Google Inc.
#
# Author: Stefan Klug <stefan.klug@ideasonboard.com>
#
# This script looks for occurrences of the debug metadata controls in the source
# tree and updates src/libcamera/control_ids_debug.yaml accordingly. It is meant
# to be used during development to ease updating of the yaml file while
# debugging.

import argparse
import logging
import os
import re
import sys
from dataclasses import dataclass
from pathlib import Path

logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO, format='%(levelname)s: %(message)s')

try:
    import ruamel.yaml as ruyaml
except:
    logger.error(
        f'Failed to import ruamel.yaml. Please install the ruamel.yaml package.')
    sys.exit(1)

@dataclass
class FoundMatch:
    file: os.PathLike
    whole_match: str
    line: int
    type: str
    name: str
    size: str = None


def get_control_name(control):
    k = list(control.keys())
    if len(k) != 1:
        raise Exception(f"Can't handle control entry with {len(k)} keys")
    return k[0]


def find_debug_controls(dir):
    extensions = ['.cpp', '.h']
    files = [p for p in dir.rglob('*') if p.suffix in extensions]

    # The following regex was tested on
    # set<Span<type>>( controls::debug::something , static_cast<type>(var) )
    # set<>( controls::debug::something , static_cast<type>(var) )
    # set( controls::debug::something , static_cast<type> (var) )
    exp = re.compile(r'set'  # set function
                     r'(?:\<((?:[^)(])*)\>)?'  # followed by a optional template param
                     r'\(\s*controls::debug::(\w+)\s*,'  # referencing a debug control
                     )
    matches = []
    for p in files:
        with p.open('r') as f:
            for idx, line in enumerate(f):
                match = exp.search(line)
                if match:
                    m = FoundMatch(file=p, line=idx, type=match.group(1),
                                   name=match.group(2), whole_match=match.group(0))
                    if m.type is not None and m.type.startswith('Span'):
                        # Simple span type detection treating the last word
                        # inside <> as type.
                        r = re.match(r'Span<(?:.*\s+)(.*)>', m.type)
                        m.type = r.group(1)
                        m.size = '[n]'
                    matches.append(m)
    return matches


def main(argv):
    parser = argparse.ArgumentParser(
        description='Automatically updates control_ids_debug.yaml')
    parser.parse_args(argv[1:])

    yaml = ruyaml.YAML()
    root_dir = Path(__file__).resolve().parent.parent
    ctrl_file = root_dir.joinpath('src/libcamera/control_ids_debug.yaml')

    matches = find_debug_controls(root_dir.joinpath('src'))

    doc = yaml.load(ctrl_file)

    controls = doc['controls']

    # Create a map of names in the existing yaml for easier updating.
    controls_map = {}
    for control in controls:
        for k, v in control.items():
            controls_map[k] = v

    obsolete_names = list(controls_map.keys())

    for m in matches:
        if not m.type:
            p = m.file.relative_to(Path.cwd(), walk_up=True)
            logger.warning(
                f'{p}:{m.line + 1}: Failed to deduce type from {m.whole_match} ... skipping')
            continue

        p = m.file.relative_to(root_dir)
        desc = {'type': m.type,
                'description': f'Debug control {m.name} found in {p}:{m.line}'}
        if m.size is not None:
            desc['size'] = m.size

        if m.name in controls_map:
            # Can't use == for modified check because of the special yaml dicts.
            update_needed = False
            if list(controls_map[m.name].keys()) != list(desc.keys()):
                update_needed = True
            else:
                for k, v in controls_map[m.name].items():
                    if v != desc[k]:
                        update_needed = True
                        break

            if update_needed:
                logger.info(f"Update control '{m.name}'")
                controls_map[m.name].clear()
                controls_map[m.name].update(desc)

            obsolete_names.remove(m.name)
        else:
            logger.info(f"Add control '{m.name}'")
            insert_before = len(controls)
            for idx, control in enumerate(controls):
                if get_control_name(control).lower() > m.name.lower():
                    insert_before = idx
                    break
            controls.insert(insert_before, {m.name: desc})

    # Remove elements from controls without recreating the list (to keep
    # comments etc.).
    idx = 0
    while idx < len(controls):
        name = get_control_name(controls[idx])
        if name in obsolete_names:
            logger.info(f"Remove control '{name}'")
            controls.pop(idx)
        else:
            idx += 1

    with ctrl_file.open('w') as f:
        # Ruyaml looses the header.
        f.write(("# SPDX-License-Identifier: LGPL-2.1-or-later\n"
                 "#\n"
                 "# This file was generated by utils/gen-debug-controls.py\n"
                 "#\n"))
        yaml.dump(doc, f)

    return 0


if __name__ == '__main__':
    sys.exit(main(sys.argv))