Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add ExternalSurfaceWidget #42

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ find_package(spdlog REQUIRED)
find_package(nlohmann_json 3 REQUIRED)

add_executable(${PROJECT_NAME} ${SOURCE_FILES})
target_link_libraries(${PROJECT_NAME} rockchip_mpp pthread drm m cairo spdlog::spdlog nlohmann_json::nlohmann_json)
target_link_libraries(${PROJECT_NAME} rockchip_mpp pthread drm m cairo spdlog::spdlog nlohmann_json::nlohmann_json rt)

# Embed gstreamer
find_package(PkgConfig REQUIRED)
Expand Down
7 changes: 7 additions & 0 deletions config_osd.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@
"format": "0.0.1",
"assets_dir": "/usr/local/share/pixelpilot/",
"widgets": [
{
"name": "msposd",
"type": "ExternalSurfaceWidget",
"x": 0,
"y": 0,
"facts": []
},
{
"name": "WFB RSSI chart",
"type": "BarChartWidget",
Expand Down
80 changes: 80 additions & 0 deletions src/osd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -950,6 +950,83 @@ class DebugWidget: public Widget {
}
};

class ExternalSurfaceWidget: public Widget {
public:
ExternalSurfaceWidget(int pos_x, int pos_y, std::string shm_name ): Widget(pos_x, pos_y), shm_name(shm_name) {};

virtual void init_shm(cairo_t *cr) {
SPDLOG_INFO("creating shm region {}", shm_name);

cairo_surface_t *target = cairo_get_target(cr);
int width = cairo_image_surface_get_width(target);
int height = cairo_image_surface_get_height(target);

// Calculate total shared memory size
shm_size = sizeof(SharedMemoryRegion) + (width * height * 4); // Metadata + Image data

// Create shared memory region
int shm_fd = shm_open(shm_name.c_str(), O_CREAT | O_RDWR, 0666);
if (shm_fd == -1) {
perror("Failed to create shared memory");
return;
}

if (ftruncate(shm_fd, shm_size) == -1) {
perror("Failed to set shared memory size");
shm_unlink(shm_name.c_str());
return;
}

// Map shared memory to process address space
auto *shm_region = static_cast<SharedMemoryRegion*>(
mmap(0, shm_size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0)
);
if (shm_region == MAP_FAILED) {
perror("Failed to map shared memory");
shm_unlink(shm_name.c_str());
return;
}

// Write metadata
shm_region->width = width;
shm_region->height = height;

// Create Cairo surface for the image data
shm_surface = cairo_image_surface_create_for_data(
shm_region->data, CAIRO_FORMAT_ARGB32, width, height, width * 4
);

// Store pointer for cleanup
shm_data = reinterpret_cast<unsigned char*>(shm_region);
}


virtual void draw(cairo_t *cr) {

if (! shm_surface)
init_shm(cr);
auto [x, y] = xy(cr);
cairo_set_source_surface(cr, shm_surface, x, y); // Position at (0, 0)
cairo_paint(cr); // Paint shm_surface onto base_surface
}

~ExternalSurfaceWidget() {
SPDLOG_INFO("bye, bye, shm region {}", shm_name);
if (shm_surface) {
cairo_surface_destroy(shm_surface);
}
if (shm_data) {
munmap(shm_data, shm_size);
}
shm_unlink(shm_name.c_str());
}

protected:
cairo_surface_t *shm_surface = nullptr;
unsigned char *shm_data = nullptr;
size_t shm_size;
std::string shm_name;
};

class Osd {
public:
Expand Down Expand Up @@ -993,6 +1070,9 @@ class Osd {
if (type == "TextWidget") {
addWidget(new TextWidget(x, y, widget_j.at("text").template get<std::string>()),
matchers);
}
else if (type == "ExternalSurfaceWidget") {
addWidget(new ExternalSurfaceWidget(x, y, name), matchers);
} else if (type == "TplTextWidget") {
auto tpl = widget_j.at("template").template get<std::string>();
addWidget(new TplTextWidget(x, y, tpl, (uint)matchers.size()), matchers);
Expand Down
6 changes: 6 additions & 0 deletions src/osd.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ typedef struct {

extern int osd_thread_signal;

struct SharedMemoryRegion {
uint16_t width; // Image width
uint16_t height; // Image height
unsigned char data[]; // Flexible array member for image data
};

void *__OSD_THREAD__(void *param);

#endif
Loading