🌐 한국어

    영상 모니터링 API#

    oasis::ui 네임스페이스 범주에서 호출됩니다.

    헤더 파일#

    OasisPreview.h

    PreviewFrameObserver 인터페이스#

    Preview 객체에 setPreviewFrameObserver 함수를 이용하여 PreviewFrameObserver에서 유도된 사용자 정의 observer 객체를 지정할 수 있습니다.

    응용 프로그램은 onFrame 콜백 함수를 통해 화면에 보여지는 영상 프레임을 얻을 수 있습니다.

    class PreviewFrameObserver : public std::enable_shared_from_this<PreviewFrameObserver>
    {
    public:
        PreviewFrameObserver();
        virtual ~PreviewFrameObserver();
        virtual void onFrame(int32_t camera_id, uint8_t *frame, int32_t stride_width, int32_t width, int32_t height);
        virtual void onNoMediaData(int32_t camera_id);
    };
    
    void onFrame ( int32_t camera_id , uint8_t * frame , int32_t stride_width , int32_t width , int32_t height )
    OasisPreview.h
    화면에 보여지는 영상 프레임을 전달합니다.
    매개변수
    camera_id  configCameras에서 지정한 카메라 ID입니다.
    frame  프레임 시작 포인터입니다.
    stride_width  프레임 너비 stride 입니다.
    width  프레임 너비입니다.
    height  프레임 높이입니다.

    영상 프레임 포맷이 YUV420인 경우, 아래와 같은 수식으로 Y,U,V 채널을 얻을 수 있습니다.

    uint8_t *y = frame;
    uint8_t *u = frame + stride_width * height;
    uint8_t *v = u + stride_width * height / 4;
    
    void onNoMediaData ( int32_t camera_id )
    OasisPreview.h
    카메라 장치로 부터 영상 정보를 일정 시간 동안 얻을 수 없을 경우 발생합니다.
    매개변수
    camera_id  configCameras에서 지정한 카메라 ID입니다.

    함수#

    PreviewRef createPreview ( int32_t display_id , key_value_map_t & parameters )
    OasisPreview.h
    Preview 객체를 생성합니다.
    매개변수
    display_id  Display 장치 ID 입니다. "0"을 지정합니다.
    parameters  Preview 객체를 생성하기 위해 필요한 key-value map입니다.
    리턴값
    성공하면 Preview 객체를 리턴하고, 실패하면 nullptr를 리턴합니다.
    기본값
    필수
    설명
    rotation
    0
     
    영상 회전 각도를 지정합니다. 0, 90, 270, 180 값중 하나를 지정합니다. 일괄적으로 회전을 지정할 경우 사용되며, channel&lt;N>-rotation 키값으로 개별 영상 채널별로 회전 각도를 지정할 수 있습니다.
    channel-count
    모니터링할 채널(카메라 장치) 개수 입니다.
    primary-channel
    주 채널 번호를 지정합니다. 시작번호는 1입니다.

    각 영상 채널에 대한 key-value map 값은 각 키값 앞에 prefix로 channel<N>- 이 붙습니다. <N>은 1부터 시작하여 1씩 증가합니다.

    기본값
    필수
    설명
    channel<N>-camera-id
    configCameras에서 지정한 모니터링 할 카메라 장치 ID입니다.
    channel<N>-ise-id
    -1
     
    AllWinner 전용 키 값으로 ISE 장치 ID입니다.
    channel<N>-rotation
    0
     
    영상 채널 회전 각도를 지정합니다. 0, 90, 270, 180 값중 하나를 지정합니다
    channel<N>-x
    영상 채널의 x좌표를 지정합니다.
    channel<N>-y
    영상 채널의 y좌표를 지정합니다.
    channel<N>-width
    영상 채널의 너비를 지정합니다.
    channel<N>-height
    영상 채널의 높이를 지정합니다.
    channel<N>-zorder
    0
     
    영상 채널의 보여지는 순번을 지정합니다. 높을 수록 앞에 보여집니다.
    channel<N>-enable-adas
    0
     
    ADAS 활성화 여부를 지정합니다. 하나의 영상 채널에서만 가능합니다.
    channel<N>-adas-inference-model-names
     
    ADAS에 적용할 추론 모델 목록입니다.
    int32_t setPreviewFrameObserver ( const PreviewRef & preview , const std::shared_ptr<PreviewFrameObserver> & observer )
    OasisPreview.h
    Preview 객체에 PreviewFrameObserver에서 유도된 사용자 정의 observer 객체를 지정합니다.
    매개변수
    preview  createPreview로 생성한 Preview 객체입니다.
    observer 
    리턴값
    • 0: 성공
    • -1: 실패
    int32_t destroyPreview ( const PreviewRef & preview )
    OasisPreview.h
    Preview 객체를 해제합니다.
    매개변수
    preview  createPreview로 생성한 Preview 객체입니다.
    리턴값
    • 0: 성공
    • -1: 실패
    int32_t previewStart ( const PreviewRef & preview )
    OasisPreview.h
    Preview를 시작합니다.
    매개변수
    preview  createPreview로 생성한 Preview 객체입니다.
    리턴값
    • 0: 성공
    • -1: 실패
    int32_t previewStop ( const PreviewRef & preview )
    OasisPreview.h
    Preview를 중지합니다.
    매개변수
    preview  createPreview로 생성한 Preview 객체입니다.
    리턴값
    • 0: 성공
    • -1: 실패
    bool previewIsRunning ( const PreviewRef & preview )
    OasisPreview.h
    Preview가 동작 중인지 확인합니다.
    매개변수
    preview  createPreview로 생성한 Preview 객체입니다.
    리턴값
    • true: 동작 중입니다.
    • false: 동작 중이 아닙니다.
    int32_t previewGetCameraIdOfChannel ( const PreviewRef & preview , const char * channel_id )
    OasisPreview.h
    Preview 객체의 채널에 연결된 카메라 장치 ID를 얻습니다.
    매개변수
    preview  createPreview로 생성한 Preview 객체입니다.
    channel_id  채널 ID 문자열입니다. 채널 1번인 경우, "channel1"로 지정합니다.
    리턴값
    • 0: 성공
    • -1: 실패
    int32_t previewShowCameraStream ( const PreviewRef & preview , int32_t camera_id , bool show )
    OasisPreview.h
    Preview 객체가 카메라 장치로 부터 출력되는 영상을 보거나 보이지게 않게 합니다.
    매개변수
    preview  createPreview로 생성한 Preview 객체입니다.
    camera_id  configCameras에서 지정한 카메라 ID입니다.
    show  true이면 카메라 영상이 보이게 하고, false이면 카메라 영상이 보이지 않게 합니다.
    리턴값
    • 0: 성공
    • -1: 실패
    bool previewIsCameraStreamShown ( const PreviewRef & preview , int32_t camera_id )
    OasisPreview.h
    카메라 영상이 보이도록 설정되었는 지 확인합니다.
    매개변수
    preview  createPreview로 생성한 Preview 객체입니다.
    camera_id  configCameras에서 지정한 카메라 ID입니다.
    리턴값
    • true: 카메라 영상이 보이도록 설정되었습니다.
    • false: 카메라 영상이 보이지 않도록 설정되었습니다.
    int32_t previewAlign ( const PreviewRef & preview , int32_t camera_id , PositionType horz_position , PositionType vert_position , bool show = true )
    OasisPreview.h
    카메라 영상 창의 위치를 조정합니다.
    매개변수
    preview  createPreview로 생성한 Preview 객체입니다.
    camera_id  configCameras에서 지정한 카메라 ID입니다.
    horz_position  수평 위치 값입니다. left, center, right 중 하나의 값을 지정합니다.
    vert_position  수직 위치 값입니다. top, center, bottom 중 하나의 값을 지정합니다.
    show  true이면 영상이 보여지고, false이면 영상이 보이지 않습니다.
    리턴값
    • 0: 성공
    • -1: 실패
    int32_t previewSetPos ( const PreviewRef & preview , int32_t camera_id , int32_t x , int32_t y )
    OasisPreview.h
    카메라 영상이 보여지는 위치를 지정합니다. 디스플레이 크기에 벗어나면 짤려서 보입니다.
    매개변수
    preview  createPreview로 생성한 Preview 객체입니다.
    camera_id  configCameras에서 지정한 카메라 ID입니다.
    x  카메라 영상의 왼쪽 위치입니다.
    y  카메라 영상의 위쪽 위치입니다.
    리턴값
    • 0: 성공
    • -1: 실패
    int32_t previewSetSize ( const PreviewRef & preview , int32_t camera_id , int32_t width , int32_t height )
    OasisPreview.h
    카메라 영상의 크기를 지정합니다. 디스플레이 크기 범위를 벗어난 경우, 짤려서 보입니다.
    매개변수
    preview  createPreview로 생성한 Preview 객체입니다.
    camera_id  configCameras에서 지정한 카메라 ID입니다.
    width  카메라 영상의 너비입니다.
    height  카메라 영상의 높이입니다.
    리턴값
    • 0: 성공
    • -1: 실패
    int32_t previewSetRect ( const PreviewRef & preview , int32_t camera_id , int32_t left , int32_t top , int32_t width , int32_t height )
    OasisPreview.h
    카메라 영상이 보이지는 위치와 크기를 지정합니다. 디스플레이 크기에 벗어나면 짤려서 보입니다.
    매개변수
    preview  createPreview로 생성한 Preview 객체입니다.
    camera_id  configCameras에서 지정한 카메라 ID입니다.
    left  카메라 영상의 왼쪽 위치입니다.
    top  카메라 영상의 위쪽 위치입니다.
    width  카메라 영상의 너비입니다.
    height  카메라 영상의 높이입니다.
    리턴값
    • 0: 성공
    • -1: 실패
    int32_t previewSetZOrder ( const PreviewRef & preview , int32_t camera_id , int32_t zorder )
    OasisPreview.h
    카메라 영상이 화면에 보이지는 순서를 지정합니다. 높을 수록 앞에 보여집니다.
    매개변수
    preview  createPreview로 생성한 Preview 객체입니다.
    camera_id  configCameras에서 지정한 카메라 ID입니다.
    zorder  보이는 순서 값입니다. 최대값에 __INT_MAX__로 제한이 없습니다.
    리턴값
    • 0: 성공
    • -1: 실패
    int32_t previewSetVisible ( const PreviewRef & preview , int32_t camera_id , bool show )
    OasisPreview.h
    카메라 영상을 보이거나 보이지 않도록 설정합니다.
    매개변수
    preview  createPreview로 생성한 Preview 객체입니다.
    camera_id  configCameras에서 지정한 카메라 ID입니다.
    show  true이면 카메라 영상이 보이게 하고, false이면 카메라 영상이 보이지 않게 합니다.
    리턴값
    • 0: 성공
    • -1: 실패
    int32_t previewIsVisible ( const PreviewRef & preview , int32_t camera_id )
    OasisPreview.h
    카메라 영상이 현재 보이도록 설정되었는 지 확인합니다.
    매개변수
    preview  createPreview로 생성한 Preview 객체입니다.
    camera_id  configCameras에서 지정한 카메라 ID입니다.
    리턴값
    • 1: 보이도록 설정되었습니다.
    • 0: 보이지 않도록 설정되었습니다.
    int32_t previewGetCameraFD ( const PreviewRef & preview , int32_t camera_id )
    OasisPreview.h
    카메라 장치가 /dev/video<N> 장치를 직접 사용하는 경우, 해당 파일 디스크립터를 얻습니다.
    매개변수
    preview  createPreview로 생성한 Preview 객체입니다.
    camera_id  configCameras에서 지정한 카메라 ID입니다.
    리턴값
    Oasis가 /dev/video<N> 장치를 열어서 획득한 핸들 번호입니다. 실패하면 -1을 리턴합니다.
    int32_t previewGetCameraLuminescenceValue ( const PreviewRef & preview , int32_t camera_id , int32_t * LV )
    OasisPreview.h
    카메라 영상의 밝기 값을 얻습니다. AllWinner 칩셋에만 적용됩니다.
    매개변수
    preview  createPreview로 생성한 Preview 객체입니다.
    camera_id  configCameras에서 지정한 카메라 ID입니다.
    LV  OUT 밝기 값을 리턴합니다.
    리턴값
    • 0: 성공
    • -1: 실패
    int32_t previewGetCameraColorTemperature ( const PreviewRef & preview , int32_t camera_id , int32_t * temperature )
    OasisPreview.h
    카메라 영상의 색상온도를 얻습니다. AllWinner 칩셋에만 적용됩니다.
    매개변수
    preview  createPreview로 생성한 Preview 객체입니다.
    camera_id  configCameras에서 지정한 카메라 ID입니다.
    temperature  OUT 온도 값을 리턴합니다.
    리턴값
    • 0: 성공
    • -1: 실패
    int32_t previewEnableWDR ( const PreviewRef & preview , int32_t camera_id , bool enable )
    OasisPreview.h
    카메라 장치에 WDR 활성화 여부를 지정합니다. AllWinner 칩셋에만 적용됩니다.
    매개변수
    preview  createPreview로 생성한 Preview 객체입니다.
    camera_id  configCameras에서 지정한 카메라 ID입니다.
    enable  true이면 WDR 활성화합니다. false이면 비활성화합니다.
    리턴값
    • 0: 성공
    • -1: 실패
    int32_t previewSetISPCfg ( const PreviewRef & preview , int32_t camera_id , int group , uint32_t flags , void * cfg_data )
    OasisPreview.h
    카메라 장치에 ISP 데이터를 설정합니다. AllWinner 칩셋에만 적용됩니다.
    매개변수
    preview  createPreview로 생성한 Preview 객체입니다.
    camera_id  configCameras에서 지정한 카메라 ID입니다.
    group  ISP 그룹 번호입니다.
    flags  플래그 값입니다.
    cfg_data  OUT 데이터 포인터입니다.
    리턴값
    • 0: 성공
    • -1: 실패
    int32_t previewGetISPCfg ( const PreviewRef & preview , int32_t camera_id , int group , uint32_t flags , void * cfg_data )
    OasisPreview.h
    카메라 장치에 적용된 ISP 설정을 얻습니다. AllWinner 칩셋에만 적용됩니다.
    매개변수
    preview  createPreview로 생성한 Preview 객체입니다.
    camera_id  configCameras에서 지정한 카메라 ID입니다.
    group  ISP 그룹 번호입니다.
    flags  플래그 값입니다.
    cfg_data  OUT 데이터 포인터입니다.
    리턴값
    • 0: 성공
    • -1: 실패
    int32_t previewSetZoom ( const PreviewRef & preview , int32_t camera_id , int32_t x , int32_t y , int32_t width , int32_t height )
    OasisPreview.h
    Preview 객체에 특정 영역을 확대해서 보여줍니다. Preview가 동작 중일 때만 적용됩니다. 높이나 너비가 음수인 경우, 영역 확대가 해제됩니다.
    매개변수
    preview  createPreview로 생성한 Preview 객체입니다.
    camera_id  configCameras에서 지정한 카메라 ID입니다.
    x  영역의 x좌표입니다.
    y  영역의 y좌표입니다.
    width  영역의 너비입니다.
    height  영역의 높이입니다.
    리턴값
    • 0: 성공
    • -1: 실패

    예제#

    아래는 카메라 장치 ID 0 영상을 모니터링하는 예입니다.

    Oasis를 초기화 합니다.

    // 파일시스템을 사용하지 않습니다.
    
    oasis::key_value_map_t parameters;
    
    parameters["offs-disable"] = "1";
    
    if(oasis::initialize(parameters) < 0) {
        DLOG(DLOG_ERROR, "Oasis init failed\n");
        return -1;
    }
    
    

    카메라 장치를 초기화 합니다. 여기서는 카메라 장치 한개를 사용합니다.

    parameters.clear();
    
    parameters["source-count"] = "1";
    
    parameters["source1-camera-id"] = "0";
    parameters["source1-isp-id"] = "0";
    parameters["source1-isp-wdr-mode"] = "0";
    parameters["source1-capture-format"] = "YUV420";
    parameters["source1-capture-buffers"] = "5";
    parameters["source1-fps"] = "30";
    parameters["source1-subchannel-rotation"] = "0";
    parameters["source1-loc"] = "front";
    parameters["source1-capture-resolution"] = "1080p";
    parameters["source1-sensor-config"] = "./Resource_tp2863/VIC/0/tp2863_1920x1080_ch0.cfg";
    parameters["source1-autoscene-config"] = "./Resource_tp2863/AutoScene/autoscene_conf.cfg";
    parameters["source1-resource-dir"] = "./Resource_tp2863/";
    
    configCameras(parameters);  
    

    디스프레이 장치를 초기화 합니다.

    parameters.clear();
    
    parameters["memory-type"] = "ion"; //cma
    parameters["screen-width"] = "480";
    parameters["screen-height"] = "320";
    
    display::setup(parameters);
    

    GUI를 설정합니다. 여기 예에서는 터치를 사용하지 않습니다.

    parameters.clear();
    
    parameters["system-font-size"] = "10";
    parameters["system-font-path"] = "/mnt/sd/consola.ttf";
    parameters["display-rotation"] = "0";
    parameters["enable-touch"] = "0";
    
    err = ui::setup(parameters);
    if (err < 0) {
        DLOG(DLOG_ERROR, "Oasis ui::setup failed\n");
        return -1;
    }
    

    Preview 객체를 초기화 합니다.

    parameters.clear();
    
    // 기본 스크린 객체를 얻고 너비와 높이를 미디어플레이어에 적용합니다.
    ui::ScreenRef screen = ui::getDefaultScreen();
    
    int32_t screen_width = ui::screenWidth(screen);
    int32_t screen_height = ui::screenHeight(screen);
    
    
    // ui::PreviewFrameObserver 에서 유도된 사용자 정의 객체를 생성합니다.
    std::shared_ptr<MyPreviewFrameObserver> observer = std::make_shared<MyPreviewFrameObserver>();
    
    parameters["channel-count"] = "1";
    parameters["primary-channel"] = "1";
    
    parameters["channel1-camera-id"] = std::to_string(camera_id);
    parameters["channel1-visible"] = "1";
    parameters["channel1-rotation"] = std::to_string(rotation);
    // 재생 화면을 전체 스크린으로 지정합니다.
    parameters["channel1-x"] = "0";
    parameters["channel1-y"] = "0";
    parameters["channel1-width"] = std::to_string(screen_width);
    parameters["channel1-height"] = std::to_string(screen_height);
    parameters["channel1-zorder"] = "0";
    
    ui::PreviewRef preview = ui::createPreview(0, parameters);
    ui::setPreviewFrameObserver(preview, observer);
    

    화면을 구성합니다. 최상위 Window 객체에 Fixed 레이아웃 컨테이너를 이용하고, 영상화면은 전체화면으로 설정합니다.

    ui::WindowRef preview_panel = ui::createWindow("Preview1");
    //ASSERT(preview_panel != nullptr);
    
    ui::FixedRef fixed_layout = ui::createFixed();
    ui::containerAdd(preview_panel, fixed_layout);
    
    ui::setFixedSize(preview, screen_width, screen_height);
    ui::fixedPut(fixed_layout, preview, 0, 0);
    ui::screenAdd(screen, preview_panel);
    
    ui::setVisible(preview_panel, true);
    

    모니터링을 시작합니다.

    ui::previewStart(preview);
    

    재생 중 화면 위치를 변경하는 예입니다.

    ui::previewSetPos(preview, 0, 100, 100)
    

    모니터링을 중지합니다.

    ui::previewStop(preview);
    

    아래는 전체 코드입니다.

    #include "OasisAPI.h"
    #include "OasisLog.h"
    #include "OasisMedia.h"
    #include "OasisUI.h"
    #include "OasisFS.h"
    #include "OasisUtil.h"
    #include "OasisDisplay.h"
    
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <dirent.h>
    
    #include <signal.h>
    
    #include <thread>
    #include <mutex>
    #include <memory>
    #include <condition_variable>
    
    using namespace oasis;
    
    
    static bool continue_previewing = true;
    
    void cancel_handler(int signum)
    {
        continue_previewing = false;
    }
    
    class MyPreviewFrameObserver : public ui::PreviewFrameObserver {
    public:
        MyPreviewFrameObserver() {}
        virtual ~MyPreviewFrameObserver() {}
    
        virtual void onFrame(int32_t camera_id, uint8_t *frame, int32_t stride_width, int32_t width, int32_t height) {
        }
        virtual void onNoMediaData(int32_t camera_id) {
            fprintf(stdout, "no media: camera<%d>\n", camera_id);
        }
    };
    
    void printUsage(const char *pgname)
    {
        fprintf(stderr, "USAGE: %s [-r <rotation. 90, 270>] <camera id>\n", pgname);
    }
    
    int main(int argc, char *argv[])
    {
        int32_t err;
        int c;
        int32_t rotation = 0;
        int32_t camera_id = -1;
    
        opterr = 0;
        while ((c = getopt(argc, argv, "r:h")) != -1) {
            switch (c) {
            case 'r':
                if(optarg == nullptr) {
                    fprintf(stderr, "error: bad option argument '%c'\n", optopt);
                    return -1;
                }
                rotation = atoi(optarg);
                if(rotation != 0 && rotation != 90 /*&& rotation != 180*/ && rotation != 270) {
                    fprintf(stderr, "bad rotation: %d\n", rotation);
                    return -1;
                }
                break;
            case 'h':
            default:
                printUsage(argv[0]);
                return -1;
            }
        }
    
        if(argc-optind < 1) {
            fprintf(stderr, "error: invalid or insufficient arguments (%d, %d)\n", argc, optind);
            printUsage(argv[0]);
            return -1;
        }
    
        camera_id = atoi(argv[optind]);
        if(camera_id < 0) {
            fprintf(stderr, "invalid camera id: %d\n", camera_id);
            return -1;
        }
    
    
        signal(SIGINT, cancel_handler);
    
        oasis::key_value_map_t parameters;
    
        ////////////////////////////////////////////////////////////////////////////////////////////
        // init
    
        parameters["offs-disable"] = "1";
    
        if(oasis::initialize(parameters) < 0) {
            DLOG(DLOG_ERROR, "Oasis init failed\n");
            return -1;
        }
    
        ////////////////////////////////////////////////////////////////////////////////////////////
        // camera sources
        parameters.clear();
    
        parameters["source-count"] = "1";
    
        parameters["source1-camera-id"] = "0";
        parameters["source1-isp-id"] = "0";
        parameters["source1-isp-wdr-mode"] = "0";
        parameters["source1-capture-format"] = "YUV420";
        parameters["source1-capture-buffers"] = "5";
        parameters["source1-fps"] = "30";
        parameters["source1-subchannel-rotation"] = "0";
        parameters["source1-loc"] = "front";
        parameters["source1-capture-resolution"] = "1080p";
        parameters["source1-sensor-config"] = "./Resource_tp2863/VIC/0/tp2863_1920x1080_ch0.cfg";
        parameters["source1-autoscene-config"] = "./Resource_tp2863/AutoScene/autoscene_conf.cfg";
        parameters["source1-resource-dir"] = "./Resource_tp2863/";
    
        configCameras(parameters);  
    
        ////////////////////////////////////////////////////////////////////////////////////////////
        // display setup
        parameters.clear();
    
        parameters["memory-type"] = "ion"; //cma
        parameters["screen-width"] = "480";
        parameters["screen-height"] = "320";
    
        display::setup(parameters);
    
    
        //////////////////////////////////////////////////////////////////////////////////////////
        // ui setup
        parameters.clear();
    
        parameters["system-font-size"] = "10";
        parameters["system-font-path"] = "/mnt/sd/consola.ttf";
    
        parameters["display-rotation"] = "0";
        parameters["enable-touch"] = "0";
    
        err = ui::setup(parameters);
        if (err < 0) {
            DLOG(DLOG_ERROR, "Oasis ui::setup failed\n");
            return -1;
        }
    
        /////////////////////////////////////////////////////////////////////////
        // create preview and layout
    
        ui::ScreenRef screen = ui::getDefaultScreen();
        //ASSERT(screen != nullptr);
    
        int32_t screen_width = ui::screenWidth(screen);
        int32_t screen_height = ui::screenHeight(screen);
    
    
        parameters.clear();
    
    
        //preview_panel
        ui::WindowRef preview_panel = ui::createWindow("Preview1");
        //ASSERT(preview_panel != nullptr);
    
        ui::FixedRef fixed_layout = ui::createFixed();
        ui::containerAdd(preview_panel, fixed_layout);
    
        std::shared_ptr<MyPreviewFrameObserver> observer = std::make_shared<MyPreviewFrameObserver>();
    
        parameters["channel-count"] = "1";
        parameters["primary-channel"] = "1";
    
        parameters["channel1-camera-id"] = std::to_string(camera_id);
        parameters["channel1-visible"] = "1";
        parameters["channel1-rotation"] = std::to_string(rotation);
        parameters["channel1-x"] = "0";
        parameters["channel1-y"] = "0";
        parameters["channel1-width"] = std::to_string(screen_width);
        parameters["channel1-height"] = std::to_string(screen_height);
        parameters["channel1-zorder"] = "0";
    
        ui::PreviewRef preview = ui::createPreview(0, parameters);
        ui::setPreviewFrameObserver(preview, observer);
    
        ui::setFixedSize(preview, screen_width, screen_height);
        ui::fixedPut(fixed_layout, preview, 0, 0);
        ui::screenAdd(screen, preview_panel);
    
        ui::setVisible(preview_panel, true);
    
        ui::previewStart(preview);
    
        do {
            usleep(100000);
        } while (continue_previewing);
    
        ui::previewStop(preview);
    
        err = ui::cleanup();
    
        oasis::finalize();
    
        return 0;
    }