Skip to content

Commit e48aba9

Browse files
authored
add ExternalSurfaceWidget (#42)
1 parent 94e3606 commit e48aba9

File tree

4 files changed

+94
-1
lines changed

4 files changed

+94
-1
lines changed

CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ find_package(spdlog REQUIRED)
3535
find_package(nlohmann_json 3 REQUIRED)
3636

3737
add_executable(${PROJECT_NAME} ${SOURCE_FILES})
38-
target_link_libraries(${PROJECT_NAME} rockchip_mpp pthread drm m cairo spdlog::spdlog nlohmann_json::nlohmann_json)
38+
target_link_libraries(${PROJECT_NAME} rockchip_mpp pthread drm m cairo spdlog::spdlog nlohmann_json::nlohmann_json rt)
3939

4040
# Embed gstreamer
4141
find_package(PkgConfig REQUIRED)

config_osd.json

+7
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22
"format": "0.0.1",
33
"assets_dir": "/usr/local/share/pixelpilot/",
44
"widgets": [
5+
{
6+
"name": "msposd",
7+
"type": "ExternalSurfaceWidget",
8+
"x": 0,
9+
"y": 0,
10+
"facts": []
11+
},
512
{
613
"name": "WFB RSSI chart",
714
"type": "BarChartWidget",

src/osd.cpp

+80
Original file line numberDiff line numberDiff line change
@@ -950,6 +950,83 @@ class DebugWidget: public Widget {
950950
}
951951
};
952952

953+
class ExternalSurfaceWidget: public Widget {
954+
public:
955+
ExternalSurfaceWidget(int pos_x, int pos_y, std::string shm_name ): Widget(pos_x, pos_y), shm_name(shm_name) {};
956+
957+
virtual void init_shm(cairo_t *cr) {
958+
SPDLOG_INFO("creating shm region {}", shm_name);
959+
960+
cairo_surface_t *target = cairo_get_target(cr);
961+
int width = cairo_image_surface_get_width(target);
962+
int height = cairo_image_surface_get_height(target);
963+
964+
// Calculate total shared memory size
965+
shm_size = sizeof(SharedMemoryRegion) + (width * height * 4); // Metadata + Image data
966+
967+
// Create shared memory region
968+
int shm_fd = shm_open(shm_name.c_str(), O_CREAT | O_RDWR, 0666);
969+
if (shm_fd == -1) {
970+
perror("Failed to create shared memory");
971+
return;
972+
}
973+
974+
if (ftruncate(shm_fd, shm_size) == -1) {
975+
perror("Failed to set shared memory size");
976+
shm_unlink(shm_name.c_str());
977+
return;
978+
}
979+
980+
// Map shared memory to process address space
981+
auto *shm_region = static_cast<SharedMemoryRegion*>(
982+
mmap(0, shm_size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0)
983+
);
984+
if (shm_region == MAP_FAILED) {
985+
perror("Failed to map shared memory");
986+
shm_unlink(shm_name.c_str());
987+
return;
988+
}
989+
990+
// Write metadata
991+
shm_region->width = width;
992+
shm_region->height = height;
993+
994+
// Create Cairo surface for the image data
995+
shm_surface = cairo_image_surface_create_for_data(
996+
shm_region->data, CAIRO_FORMAT_ARGB32, width, height, width * 4
997+
);
998+
999+
// Store pointer for cleanup
1000+
shm_data = reinterpret_cast<unsigned char*>(shm_region);
1001+
}
1002+
1003+
1004+
virtual void draw(cairo_t *cr) {
1005+
1006+
if (! shm_surface)
1007+
init_shm(cr);
1008+
auto [x, y] = xy(cr);
1009+
cairo_set_source_surface(cr, shm_surface, x, y); // Position at (0, 0)
1010+
cairo_paint(cr); // Paint shm_surface onto base_surface
1011+
}
1012+
1013+
~ExternalSurfaceWidget() {
1014+
SPDLOG_INFO("bye, bye, shm region {}", shm_name);
1015+
if (shm_surface) {
1016+
cairo_surface_destroy(shm_surface);
1017+
}
1018+
if (shm_data) {
1019+
munmap(shm_data, shm_size);
1020+
}
1021+
shm_unlink(shm_name.c_str());
1022+
}
1023+
1024+
protected:
1025+
cairo_surface_t *shm_surface = nullptr;
1026+
unsigned char *shm_data = nullptr;
1027+
size_t shm_size;
1028+
std::string shm_name;
1029+
};
9531030

9541031
class Osd {
9551032
public:
@@ -993,6 +1070,9 @@ class Osd {
9931070
if (type == "TextWidget") {
9941071
addWidget(new TextWidget(x, y, widget_j.at("text").template get<std::string>()),
9951072
matchers);
1073+
}
1074+
else if (type == "ExternalSurfaceWidget") {
1075+
addWidget(new ExternalSurfaceWidget(x, y, name), matchers);
9961076
} else if (type == "TplTextWidget") {
9971077
auto tpl = widget_j.at("template").template get<std::string>();
9981078
addWidget(new TplTextWidget(x, y, tpl, (uint)matchers.size()), matchers);

src/osd.hpp

+6
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@ typedef struct {
1414

1515
extern int osd_thread_signal;
1616

17+
struct SharedMemoryRegion {
18+
uint16_t width; // Image width
19+
uint16_t height; // Image height
20+
unsigned char data[]; // Flexible array member for image data
21+
};
22+
1723
void *__OSD_THREAD__(void *param);
1824

1925
#endif

0 commit comments

Comments
 (0)