Skip to content

Commit

Permalink
Merge pull request #74 from taorye/dev
Browse files Browse the repository at this point in the history
feat: app_uvc_camera and a little fix
  • Loading branch information
Neutree authored Dec 20, 2024
2 parents 668cc68 + b6ff7e9 commit 068ccac
Show file tree
Hide file tree
Showing 11 changed files with 257 additions and 7 deletions.
44 changes: 44 additions & 0 deletions components/vision/port/linux/maix_uvc_stream.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#include <bits/stdc++.h>
#include <functional>

#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>

#include "maix_uvc_stream.hpp"

extern "C" {

extern int uvc_main_exist;
extern int uvc_main(int argc, char *argv[]);

int uvc_video_fill_mjpg_buffer(void *buf, uint32_t *size) {
return -1;
}

}

namespace maix::uvc
{
int helper_fill_mjpg_image(void* buf, uint32_t* size, image::Image *img) {
return -1;
}

// 静态成员定义
UvcServer *UvcServer::_instance = nullptr;

void UvcServer::run() { }

void UvcServer::stop() { }

UvcStreamer::UvcStreamer(): _using_jpeg(0) { }

UvcStreamer::~UvcStreamer() { }


err::Err UvcStreamer::show(image::Image *img) {
return err::ERR_NOT_IMPL;
}

}
7 changes: 0 additions & 7 deletions components/vision/port/maixcam/maix_uvc_stream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,6 @@ void UvcServer::stop() {
maix::log::info("server restart\r\n");
}

/**
* cannot include it, because it brokes maixpy_wrapper.cpp:1027:38: error: expected unqualified-id before numeric constant
* 1027 | .value("SEEK_SET", fs::SEEK::SEEK_SET)
*/
// #include <fcntl.h>
#define O_RDWR 2

#define atomic_load(ptr) __atomic_load_n(ptr, __ATOMIC_SEQ_CST)
#define atomic_store(ptr, value) __atomic_store_n(ptr, value, __ATOMIC_SEQ_CST)

Expand Down
9 changes: 9 additions & 0 deletions projects/app_uvc_camera/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

build
dist
.config.mk
.flash.conf.json
data

/CMakeLists.txt

12 changes: 12 additions & 0 deletions projects/app_uvc_camera/app.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
id: uvc_camera
name: UVC Camera
name[zh]: UVC相机
version: 1.0.0
icon: assets/uvc_camera.json
author: Sipeed Ltd
desc: UVC Camera APP, show pictures on your PC
desc[zh]: UVC照相机应用,在你的电脑上显示画面
files:
app.yaml: app.yaml
assets: assets

Binary file added projects/app_uvc_camera/assets/ret.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions projects/app_uvc_camera/assets/uvc_camera.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"v":"5.5.7","fr":24,"ip":0,"op":113,"w":1920,"h":1080,"nm":"Comp 1","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","td":1,"sr":1,"ks":{"o":{"a":0,"k":33,"ix":11},"r":{"a":0,"k":59,"ix":10},"p":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0,"y":0},"t":75,"s":[1400.934,956.094,0],"to":[-108.884,-112.133,0],"ti":[108.884,112.133,0]},{"t":105,"s":[747.632,283.294,0]}],"ix":2},"a":{"a":0,"k":[528.07,304.922,0],"ix":1},"s":{"a":0,"k":[96.184,121.047,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[26.73,373.958],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[600.746,307.39],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 2","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[83.859,357.844],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[528.07,304.922],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Shape Layer 2","tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[1023.744,558.744,0],"ix":2},"a":{"a":0,"k":[63.744,18.744,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[307.488,307.488],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0.463,-0.522],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[104.865,104.865],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"red dot","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.915],"y":[-0.033]},"t":60.177,"s":[0]},{"t":72,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[630.655,239.905,0],"ix":2},"a":{"a":0,"k":[-297.38,-258.381,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[83.238,83.238],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0.958700980392,0.21661825741,0.41830405441,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-297.38,-258.381],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"lense","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.144],"y":[1]},"o":{"x":[0],"y":[0]},"t":45,"s":[0]},{"t":62,"s":[100]}],"ix":11},"r":{"a":0,"k":46,"ix":10},"p":{"a":0,"k":[960,540,0],"ix":2},"a":{"a":0,"k":[56.474,62.473,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0,0,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":45,"s":[0,0,100]},{"t":62,"s":[100,100,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[262.946,262.946],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0.057923238418,0.080224459779,0.351317401961,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[56.474,62.473],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[120.413,120.413],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"focal","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0],"y":[1]},"o":{"x":[1],"y":[0]},"t":23.764,"s":[0]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.703],"y":[0]},"t":24,"s":[0]},{"t":46.12109375,"s":[100]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":28,"s":[-103]},{"t":42,"s":[0]}],"ix":10},"p":{"a":0,"k":[960,540,0],"ix":2},"a":{"a":0,"k":[-13.47,25.53,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":0,"s":[-8.103,-8.103,100]},{"i":{"x":[0,0,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":28,"s":[36.897,36.897,100]},{"t":42,"s":[100,100,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[393.059,393.059],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-13.47,25.53],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"body","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[960,540,0],"ix":2},"a":{"a":0,"k":[115.847,26.596,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0,0,0.667],"y":[1,1,1]},"o":{"x":[1,1,0.333],"y":[0,0,0]},"t":0,"s":[20.607,20.764,100]},{"t":28,"s":[102.607,103.391,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[867.692,785.192],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":121,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.913725550034,0.898039275525,0.898039275525,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[115.847,26.596],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":120,"st":0,"bm":0}],"markers":[]}
9 changes: 9 additions & 0 deletions projects/app_uvc_camera/compile/priority.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# component register priority
# The upper components have higher priority
# comments start with `#`

basic
lvgl
main
uvc

74 changes: 74 additions & 0 deletions projects/app_uvc_camera/main/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
############### Add include ###################
list(APPEND ADD_INCLUDE "include"
)
list(APPEND ADD_PRIVATE_INCLUDE "")
###############################################

############ Add source files #################
# list(APPEND ADD_SRCS "src/main.c"
# "src/test.c"
# )
append_srcs_dir(ADD_SRCS "src") # append source file in src dir to var ADD_SRCS
# list(REMOVE_ITEM COMPONENT_SRCS "src/test2.c")
# FILE(GLOB_RECURSE EXTRA_SRC "src/*.c")
# FILE(GLOB EXTRA_SRC "src/*.c")
# list(APPEND ADD_SRCS ${EXTRA_SRC})
# aux_source_directory(src ADD_SRCS) # collect all source file in src dir, will set var ADD_SRCS
# append_srcs_dir(ADD_SRCS "src") # append source file in src dir to var ADD_SRCS
# list(REMOVE_ITEM COMPONENT_SRCS "src/test.c")
# set(ADD_ASM_SRCS "src/asm.S")
# list(APPEND ADD_SRCS ${ADD_ASM_SRCS})
# SET_PROPERTY(SOURCE ${ADD_ASM_SRCS} PROPERTY LANGUAGE C) # set .S ASM file as C language
# SET_SOURCE_FILES_PROPERTIES(${ADD_ASM_SRCS} PROPERTIES COMPILE_FLAGS "-x assembler-with-cpp -D BBBBB")
###############################################

###### Add required/dependent components ######
list(APPEND ADD_REQUIREMENTS basic nn vision)
###############################################

###### Add link search path for requirements/libs ######
# list(APPEND ADD_LINK_SEARCH_PATH "${CONFIG_TOOLCHAIN_PATH}/lib")
# list(APPEND ADD_REQUIREMENTS pthread m) # add system libs, pthread and math lib for example here
# set (OpenCV_DIR opencv/lib/cmake/opencv4)
# find_package(OpenCV REQUIRED)
###############################################

############ Add static libs ##################
# list(APPEND ADD_STATIC_LIB "lib/libtest.a")
###############################################

#### Add compile option for this component ####
#### Just for this component, won't affect other
#### modules, including component that depend
#### on this component
# list(APPEND ADD_DEFINITIONS_PRIVATE -DAAAAA=1)

#### Add compile option for this component
#### and components depend on this component
# list(APPEND ADD_DEFINITIONS -DAAAAA222=1
# -DAAAAA333=1)
###############################################

############ Add static libs ##################
#### Update parent's variables like CMAKE_C_LINK_FLAGS
# set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -Wl,--start-group libmaix/libtest.a -ltest2 -Wl,--end-group" PARENT_SCOPE)
###############################################

######### Add files need to download #########
# list(APPEND ADD_FILE_DOWNLOADS "{
# 'url': 'https://*****/abcde.tar.xz',
# 'urls': [], # backup urls, if url failed, will try urls
# 'sites': [], # download site, user can manually download file and put it into dl_path
# 'sha256sum': '',
# 'filename': 'abcde.tar.xz',
# 'path': 'toolchains/xxxxx',
# 'check_files': []
# }"
# )
#
# then extracted file in ${DL_EXTRACTED_PATH}/toolchains/xxxxx,
# you can directly use then, for example use it in add_custom_command
##############################################

# register component, DYNAMIC or SHARED flags will make component compiled to dynamic(shared) lib
register_component()
Empty file.
3 changes: 3 additions & 0 deletions projects/app_uvc_camera/main/include/main.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#pragma once


105 changes: 105 additions & 0 deletions projects/app_uvc_camera/main/src/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#include <bits/stdc++.h>
#include <functional>

using namespace std;
using namespace chrono_literals;

#include "maix_basic.hpp"
#include "maix_vision.hpp"
#include "maix_touchscreen.hpp"
#include "maix_uvc_stream.hpp"

using namespace maix;

#include "main.h"

static std::unique_ptr<camera::Camera> pCam = nullptr;

int my_uvc_video_fill_mjpg_buffer(void *buf, uint32_t *size) {
static uint64_t frame_count = 0;
static uint64_t last_ms;
if (!pCam) return 1;

image::Image *img = pCam->read();
if (!img) return 1;
uint64_t curr_ms_takeframe = time::ticks_ms();

std::ostringstream oss;
oss << "frame[" << img->width() << "x" << img->height() << "]: " << frame_count;
img->draw_string(4, 32, oss.str(), image::Color::from_rgb(255, 0, 0), 1.3);

uvc::helper_fill_mjpg_image(buf, size, img);
uint64_t curr_ms_mjpgframe = time::ticks_ms();

delete img;
#if 0
char result_bin_name[32];
sprintf((char *)result_bin_name, "/root/res/res_%llu.jpg", frame_count);
ofstream((const char*)result_bin_name, std::ios::binary)
.write(reinterpret_cast<char*>(buf), *size);
#endif

uint64_t curr_ms = time::ticks_ms();
static uint32_t flip = 1;
if(flip^=1) log::info("[%llu]loop use %lld ms, %.2ffps, %d bytes\r\n"
"\ttake: %lld ms\r\n"
"\tto_mjpg: %lld ms\r\n", frame_count++, curr_ms - last_ms, 1000.f/(curr_ms - last_ms), *size,
curr_ms_takeframe - last_ms, curr_ms_mjpgframe - curr_ms_takeframe);
last_ms = curr_ms;
return 0;
}

int _main(int argc, char *argv[])
{
int ret = 0;
log::info("Program start");


image::Image *ret_img = image::load("./assets/ret.png", image::Format::FMT_RGB888);
if (!ret_img)
{
log::error("load ret image failed");
return -12345;
}
display::Display disp = display::Display();
image::Image img(disp.width(), disp.height());
img.draw_image(0, 0, *ret_img);
disp.show(img);

log::info("open camera now");
camera::Camera cam = camera::Camera(1280, 720, image::Format::FMT_RGB888, "", 60, 3);
if(!pCam) pCam = make_unique<camera::Camera>(std::move(cam));
log::info("open camera success");

touchscreen::TouchScreen ts;
int ts_x = 0, ts_y = 0;
bool ts_pressed = false;

std::unique_ptr<uvc::UvcServer> pUvc = std::make_unique<uvc::UvcServer>(my_uvc_video_fill_mjpg_buffer);
pUvc->run();
img.draw_string(100, disp.height()/2, std::string("UVC started."), image::Color::from_rgb(0, 255, 0), 1.3);
disp.show(img);
while (!app::need_exit())
{
std::this_thread::sleep_for(300ms);
ts.read(ts_x, ts_y, ts_pressed);
if (ts_pressed && ts_x < 40 + 60 && ts_y < 40)
break;
}
pUvc->stop();

log::info("Program exit");

return ret;
}

int main(int argc, char *argv[])
{
// Catch signal and process
sys::register_default_signal_handle();

// Use CATCH_EXCEPTION_RUN_RETURN to catch exception,
// if we don't catch exception, when program throw exception, the objects will not be destructed.
// So we catch exception here to let resources be released(call objects' destructor) before exit.
CATCH_EXCEPTION_RUN_RETURN(_main, -1, argc, argv);
}

0 comments on commit 068ccac

Please sign in to comment.