/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2020, Google Inc. * * camera_stream.h - Camera HAL stream */ #pragma once #include #include #include #include #include #include #include #include #include #include #include "camera_request.h" #include "post_processor.h" class CameraDevice; class PlatformFrameBufferAllocator; class CameraStream { public: /* * Enumeration of CameraStream types. * * A camera stream associates an Android stream to a libcamera stream. * This enumeration describes how the two streams are associated and how * and where data produced from libcamera are delivered to the * Android framework. * * Direct: * * The Android stream is directly mapped onto a libcamera stream: frames * are delivered by the library directly in the memory location * specified by the Android stream (buffer_handle_t->data) and provided * to the framework as they are. The Android stream characteristics are * directly translated to the libcamera stream configuration. * * +-----+ +-----+ * | A | | L | * +-----+ +-----+ * | | * V V * +-----+ +------+ * | B |<---------------| FB | * +-----+ +------+ * * * Internal: * * Data for the Android stream is produced by processing a libcamera * stream created by the HAL for that purpose. The libcamera stream * needs to be supplied with intermediate buffers where the library * delivers frames to be processed and then provided to the framework. * The libcamera stream configuration is not a direct translation of the * Android stream characteristics, but it describes the format and size * required for the processing procedure to produce frames in the * Android required format. * * +-----+ +-----+ * | A | | L | * +-----+ +-----+ * | | * V V * +-----+ +------+ * | B | | FB | * +-----+ +------+ * ^ | * |-------Processing------| * * * Mapped: * * Data for the Android stream is produced by processing a libcamera * stream associated with another CameraStream. Mapped camera streams do * not need any memory to be reserved for them as they process data * produced by libcamera for a different stream whose format and size * are compatible with the processing procedure requirements to produce * frames in the Android required format. * * +-----+ +-----+ +-----+ * | A | | A' | | L | * +-----+ +-----+ +-----+ * | | | * V V V * +-----+ +-----+ +------+ * | B | | B' |<---------| FB | * +-----+ +-----+ +------+ * ^ | * |--Processing--| * * * -------------------------------------------------------------------- * A = Android stream * L = libcamera stream * B = memory buffer * FB = libcamera FrameBuffer * "Processing" = Frame processing procedure (Encoding, scaling etc) */ enum class Type { Direct, Internal, Mapped, }; CameraStream(CameraDevice *const cameraDevice, libcamera::CameraConfiguration *config, Type type, camera3_stream_t *camera3Stream, CameraStream *const sourceStream, unsigned int index); CameraStream(CameraStream &&other); ~CameraStream(); Type type() const { return type_; } camera3_stream_t *camera3Stream() const { return camera3Stream_; } const libcamera::StreamConfiguration &configuration() const; libcamera::Stream *stream() const; CameraStream *sourceStream() const { return sourceStream_; } int configure(); int process(Camera3RequestDescriptor::StreamBuffer *streamBuffer); libcamera::FrameBuffer *getBuffer(); void putBuffer(libcamera::FrameBuffer *buffer); void flush(); private: class PostProcessorWorker : public libcamera::Thread { public: enum class State { Stopped, Running, Flushing, }; PostProcessorWorker(PostProcessor *postProcessor); ~PostProcessorWorker(); void start(); void queueRequest(Camera3RequestDescriptor::StreamBuffer *request); void flush(); protected: void run() override; private: PostProcessor *postProcessor_; libcamera::Mutex mutex_; libcamera::ConditionVariable cv_; std::queue requests_ LIBCAMERA_TSA_GUARDED_BY(mutex_); State state_ LIBCAMERA_TSA_GUARDED_BY(mutex_) = State::Stopped; }; int waitFence(int fence); CameraDevice *const cameraDevice_; const libcamera::CameraConfiguration *config_; const Type type_; camera3_stream_t *camera3Stream_; CameraStream *const sourceStream_; const unsigned int index_; std::unique_ptr allocator_; std::vector> allocatedBuffers_; std::vector buffers_ LIBCAMERA_TSA_GUARDED_BY(mutex_); /* * The class has to be MoveConstructible as instances are stored in * an std::vector in CameraDevice. */ std::unique_ptr mutex_; std::unique_ptr postProcessor_; std::unique_ptr worker_; }; 68'>68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
# SPDX-License-Identifier: BSD-2-Clause
#
# Copyright (C) 2019, Raspberry Pi (Trading) Limited
#
# ctt_pretty_print_json.py - camera tuning tool JSON formatter

import sys


class JSONPrettyPrinter(object):
    """
    Take a collapsed JSON file and make it more readable
    """
    def __init__(self, fout):
        self.state = {
            "indent": 0,
            "inarray": [False],
            "arraycount": [],
            "skipnewline": True,
            "need_indent": False,
            "need_space": False,
        }

        self.fout = fout

    def newline(self):
        if not self.state["skipnewline"]:
            self.fout.write('\n')
            self.state["need_indent"] = True
            self.state["need_space"] = False
        self.state["skipnewline"] = True

    def write(self, c):
        if self.state["need_indent"]:
            self.fout.write(' ' * self.state["indent"] * 4)
            self.state["need_indent"] = False
        if self.state["need_space"]:
            self.fout.write(' ')
            self.state["need_space"] = False
        self.fout.write(c)
        self.state["skipnewline"] = False

    def process_char(self, c):
        if c == '{':
            self.newline()
            self.write(c)
            self.state["indent"] += 1
            self.newline()
        elif c == '}':
            self.state["indent"] -= 1
            self.newline()
            self.write(c)
        elif c == '[':
            self.newline()
            self.write(c)
            self.state["indent"] += 1
            self.newline()
            self.state["inarray"] = [True] + self.state["inarray"]
            self.state["arraycount"] = [0] + self.state["arraycount"]
        elif c == ']':
            self.state["indent"] -= 1
            self.newline()
            self.state["inarray"].pop(0)
            self.state["arraycount"].pop(0)
            self.write(c)
        elif c == ':':
            self.write(c)
            self.state["need_space"] = True
        elif c == ',':
            if not self.state["inarray"][0]:
                self.write(c)
                self.newline()
            else:
                self.write(c)
                self.state["arraycount"][0] += 1
                if self.state["arraycount"][0] == 16:
                    self.state["arraycount"][0] = 0
                    self.newline()
                else:
                    self.state["need_space"] = True
        elif c.isspace():
            pass
        else:
            self.write(c)

    def print(self, string):
        for c in string:
            self.process_char(c)
        self.newline()


def pretty_print_json(str_in, output_filename):
    with open(output_filename, "w") as fout:
        printer = JSONPrettyPrinter(fout)
        printer.print(str_in)


if __name__ == '__main__':
    if len(sys.argv) != 2:
        print("Usage: %s filename" % sys.argv[0])
        sys.exit(1)

    input_filename = sys.argv[1]
    with open(input_filename, "r") as fin:
        printer = JSONPrettyPrinter(sys.stdout)
        printer.print(fin.read())