Skip to content

Commit

Permalink
Preparing for bitmap uploads, restructuring some parts for better und…
Browse files Browse the repository at this point in the history
…erstanding
  • Loading branch information
wberube committed Apr 5, 2024
1 parent 9ce6792 commit 52b4beb
Show file tree
Hide file tree
Showing 5 changed files with 135 additions and 63 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Parameters for each region can be passed in one or many calls:
curl "192.168.1.17:9000/api/osd/0?font=comic&size=32.0&text=Frontdoor"
curl 192.168.1.17:9000/api/osd/0?posy=72
```
N.B. Ampersands require the address to be enclosed with double quotes under Windows or to be escaped with a backslash under Unix OSes

Supported fonts (sourced from /usr/share/fonts/truetype/) can render Unicode characters:
```
Expand All @@ -27,9 +28,9 @@ curl 192.168.1.17:9000/api/osd/1?text=

Specifiers starting with a dollar sign are used to represent real-time statistics:
```
curl "192.168.1.17:9000/api/osd/1?text=$B%20C:$C%20M:$M"
curl 192.168.1.17:9000/api/osd/1?text=$B%20C:$C%20M:$M
```
N.B. Spaces have to be escaped with %20 in URL syntaxes
N.B. Spaces have to be escaped with %20 in curl URL syntaxes

Showing the time and customizing the time format is done this way:
```
Expand Down
1 change: 1 addition & 0 deletions osd/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ extern "C"
#endif

#define starts_with(a, b) !strncmp(a, b, strlen(b))
#define equals(a, b) !strcmp(a, b)
#define ends_with(a, b) \
size_t alen = strlen(a); \
size_t blen = strlen(b); \
Expand Down
144 changes: 98 additions & 46 deletions osd/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,24 @@ static void fill(char* str)
unsigned int rxb_l, txb_l, cpu_l[6];
char out[80] = "";
char param = 0;
int i = 0, j = 0;
int ipos = 0, opos = 0;

while(str[i] != 0)
while(str[ipos] != 0)
{
if (str[i] != '$')
if (str[ipos] != '$')
{
strncat(out, str + i, 1);
j++;
strncat(out, str + ipos, 1);
opos++;
}
else if (str[i + 1] == 'B')
else if (str[ipos + 1] == 'B')
{
i++;
ipos++;
struct ifaddrs *ifaddr, *ifa;
if (getifaddrs(&ifaddr) == -1) continue;

for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
{
if (!strcmp(ifa->ifa_name, "lo")) continue;
if (equals(ifa->ifa_name, "lo")) continue;
if (!ifa->ifa_addr || ifa->ifa_addr->sa_family != AF_PACKET) continue;
if (!ifa->ifa_data) continue;

Expand All @@ -40,17 +40,17 @@ static void fill(char* str)
sprintf(b, "R:%dKbps S:%dKbps",
(stats->rx_bytes - rxb_l) / 1024, (stats->tx_bytes - txb_l) / 1024);
strcat(out, b);
j += strlen(b);
opos += strlen(b);
rxb_l = stats->rx_bytes;
txb_l = stats->tx_bytes;
break;
}

freeifaddrs(ifaddr);
}
else if (str[i + 1] == 'C')
else if (str[ipos + 1] == 'C')
{
i++;
ipos++;
char tmp[6];
unsigned int cpu[6];
FILE *stat = fopen("/proc/stat", "r");
Expand All @@ -62,13 +62,13 @@ static void fill(char* str)
char avg = 100 - (cpu[3] - cpu_l[3]) / sysconf(_SC_NPROCESSORS_ONLN);
sprintf(c, "%d%%", avg);
strcat(out, c);
j += strlen(c);
opos += strlen(c);
for (int i = 0; i < sizeof(cpu) / sizeof(cpu[0]); i++)
cpu_l[i] = cpu[i];
}
else if (str[i + 1] == 'M')
else if (str[ipos + 1] == 'M')
{
i++;
ipos++;
struct sysinfo si;
sysinfo(&si);

Expand All @@ -77,21 +77,21 @@ static void fill(char* str)
short total = si.totalram / 1024 / 1024;
sprintf(m, "%d/%dMB", used, total);
strcat(out, m);
j += strlen(m);
opos += strlen(m);
}
else if (str[i + 1] == 't')
else if (str[ipos + 1] == 't')
{
i++;
ipos++;
char s[64];
time_t t = time(NULL);
struct tm *tm = gmtime(&t);
strftime(s, 64, timefmt, tm);
strcat(out, s);
j += strlen(s);
opos += strlen(s);
}
else if (str[i + 1] == 'T')
else if (str[ipos + 1] == 'T')
{
i++;
ipos++;
#ifdef __SIGMASTAR__
unsigned short temp = 1370 * (400 - ((unsigned short*)io_map)[0x2918 >> 1]) / 1000.0f + 27;
#elif defined(__16CV300__)
Expand All @@ -102,14 +102,14 @@ static void fill(char* str)
char t[8];
sprintf(t, "%d", temp);
strcat(out, t);
j += strlen(t);
opos += strlen(t);
}
else if (str[i + 1] == '$') {
i++;
else if (str[ipos + 1] == '$') {
ipos++;
strcat(out, "$");
j++;
opos++;
}
i++;
ipos++;
}
strncpy(str, out, 80);
}
Expand All @@ -120,7 +120,8 @@ void overlays()
{
for (int id = 0; id < MAX_OSD; id++)
{
if ((!empty(osds[id].text) && !osds[id].updt) || (empty(osds[id].text) && osds[id].updt)) {
if (!empty(osds[id].text))
{
char out[80];
strcpy(out, osds[id].text);
if (strstr(out, "$"))
Expand All @@ -129,21 +130,32 @@ void overlays()
osds[id].updt = 1;
}

RECT rect = measure_text(osds[id].font, osds[id].size, out);
create_region(0, id, osds[id].posx, osds[id].posy, rect.width, rect.height);
if (osds[id].updt) {
RECT rect = measure_text(osds[id].font, osds[id].size, out);
create_region(id, osds[id].posx, osds[id].posy, rect.width, rect.height);

BITMAP bitmap = raster_text(osds[id].font, osds[id].size, out);
BITMAP bitmap = raster_text(osds[id].font, osds[id].size, out);
#ifdef __SIGMASTAR__
int s32Ret = MI_RGN_SetBitMap(id, (MI_RGN_Bitmap_t *)(&bitmap));
int s32Ret = MI_RGN_SetBitMap(id, (MI_RGN_Bitmap_t *)(&bitmap));
#else
int s32Ret = HI_MPI_RGN_SetBitMap(id, (BITMAP_S *)(&bitmap));
int s32Ret = HI_MPI_RGN_SetBitMap(id, (BITMAP_S *)(&bitmap));
#endif
if (s32Ret)
fprintf(stderr, "[%s:%d]RGN_SetBitMap failed with %#x %d!\n", __func__, __LINE__, s32Ret, id);
free(bitmap.pData);
if (s32Ret)
fprintf(stderr, "[%s:%d]RGN_SetBitMap failed with %#x %d!\n", __func__, __LINE__, s32Ret, id);
free(bitmap.pData);
}
}
else if (empty(osds[id].text) && osds[id].updt)
{
char img[32];
sprintf(img, "/tmp/osd%d.bmp", id);
fprintf(stderr, "access=%s %d\n", img, access(img, F_OK));
if (!access(img, F_OK))
load_region(id, PIXEL_FORMAT_1555);
else
unload_region(id);
osds[id].updt = 0;
}

osds[id].updt = 0;
}
sleep(1);
}
Expand All @@ -155,27 +167,68 @@ void route()
uri[9] >= '0' && uri[9] <= (MAX_OSD - 1 + '0'))
{
char id = uri[9] - '0';
if (!empty(query))
if (equals(method, "POST"))
{
char *type = request_header("Content-Type");
if (starts_with(type, "multipart/form-data"))
{
char *bound = strstr(type, "boundary=") + strlen("boundary=");
char *payloadb = strstr(payload, bound) + strlen(bound) + 2;
payloadb = strstr(payloadb, "\r\n\r\n") + 4;

void *payloade = memmem(
payloadb, payload_size - (payloadb - payload),
bound, strlen(bound));
payloade -= 4;

char path[32];
sprintf(path, "/tmp/osd%d.bmp", id);
FILE *img = fopen(path, "wb");
fwrite(payloadb, sizeof(char), (char*)payloade - payloadb, img);
fclose(img);

strcpy(osds[id].text, "");
osds[id].updt = 1;

printf(\
"HTTP/1.1 200 OK\r\n" \
"Connection: close\r\n" \
"\r\n" \
);
}
else
{
printf(\
"HTTP/1.1 415 Unsupported Media Type\r\n" \
"Content-Type: text/plain\r\n" \
"Connection: close\r\n\r\n" \
"\r\n" \
"The payload must be presented as multipart/form-data.\r\n" \
);
}
return;
}
else if (!empty(query))
{
char *remain;
for (char *item; (item = extract_pair(&query));) {
char *value = item;
char *key = extract_key(&value);
if (!strcmp(key, "font"))
if (equals(key, "font"))
strcpy(osds[id].font, !empty(value) ? value : DEF_FONT);
else if (!strcmp(key, "text"))
else if (equals(key, "text"))
strcpy(osds[id].text, value);
else if (!strcmp(key, "size")) {
else if (equals(key, "size")) {
double result = strtod(value, &remain);
if (remain == value) continue;
osds[id].size = (result != 0 ? result : DEF_SIZE);
}
else if (!strcmp(key, "posx")) {
else if (equals(key, "posx")) {
short result = strtol(value, &remain, 10);
if (remain != value)
osds[id].posx = result;
}
else if (!strcmp(key, "posy")) {
else if (equals(key, "posy")) {
short result = strtol(value, &remain, 10);
if (remain != value)
osds[id].posy = result;
Expand All @@ -193,7 +246,7 @@ void route()
id, osds[id].posx, osds[id].posy, osds[id].font, osds[id].size, osds[id].text);
return;
}
else if (!strcmp(uri, "/api/time"))
else if (equals(uri, "/api/time"))
{
struct timespec t;
if (!empty(query))
Expand All @@ -203,9 +256,9 @@ void route()
for (char *item; (item = extract_pair(&input));) {
char *value = item;
char *key = extract_key(&value);
if (!strcmp(key, "fmt"))
if (equals(key, "fmt"))
strncpy(timefmt, value, 32);
else if (!strcmp(key, "ts")) {
else if (equals(key, "ts")) {
long result = strtol(value, &remain, 10);
if (remain == value) continue;
t.tv_sec = result;
Expand All @@ -217,7 +270,6 @@ void route()
clock_gettime(CLOCK_REALTIME, &t);
printf(\
"HTTP/1.1 200 OK\r\n" \
"Content-Type: application/json;charset=UTF-8\r\n" \
"Connection: close\r\n" \
"\r\n" \
);
Expand Down
45 changes: 31 additions & 14 deletions osd/region.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

const double inv16 = 1.0 / 16.0;

int create_region(int channel, int handle, int x, int y, int width, int height)
int create_region(int handle, int x, int y, int width, int height)
{
int s32Ret;
#ifdef __SIGMASTAR__
Expand All @@ -13,6 +13,8 @@ int create_region(int channel, int handle, int x, int y, int width, int height)

MI_RGN_ChnPortParam_t stChnAttr;
MI_RGN_ChnPortParam_t stChnAttrCurrent;

stChn.eModId = E_MI_RGN_MODID_VPE;
#else
MPP_CHN_S stChn;

Expand All @@ -21,19 +23,11 @@ int create_region(int channel, int handle, int x, int y, int width, int height)

RGN_CHN_ATTR_S stChnAttr;
RGN_CHN_ATTR_S stChnAttrCurrent;
#endif

int enPixelFmt;
unsigned int au32BgColor[3] = {0xffffffff, 0x0000000, 1};

#ifdef __SIGMASTAR__
stChn.eModId = E_MI_RGN_MODID_VPE;
#else
stChn.enModId = HI_ID_VENC;
#endif
stChn.s32DevId = 0;
stChn.s32ChnId = channel;

stChn.s32ChnId = 0;
#ifdef __SIGMASTAR__
stRegion.eType = E_MI_RGN_TYPE_OSD;
stRegion.stOsdInitParam.stSize.u32Height = height;
Expand All @@ -45,13 +39,12 @@ int create_region(int channel, int handle, int x, int y, int width, int height)
stRegion.unAttr.stOverlay.stSize.u32Width = width;
stRegion.unAttr.stOverlay.u32CanvasNum = 2;
stRegion.unAttr.stOverlay.enPixelFmt = PIXEL_FORMAT_1555;
stRegion.unAttr.stOverlay.u32BgColor = au32BgColor[1];
stRegion.unAttr.stOverlay.u32BgColor = (unsigned int[]){0xffffffff, 0x00000000, 1};
#endif

#ifdef __SIGMASTAR__
// MI_RGN_DetachFromChn(handle, &stChn);
// MI_RGN_Destroy(handle);
// memset(&stRegionCurrent, 0, sizeof(MI_RGN_Attr_t));
s32Ret = MI_RGN_GetAttr(handle, &stRegionCurrent);
#else
// HI_MPI_RGN_DetachFromChn(HandleNum,&stChn);
Expand Down Expand Up @@ -324,8 +317,32 @@ int load_region(unsigned int handle, int enPixelFmt)
prepare_bitmap(path, bitmap, 0, 0, enPixelFmt);

int s32Ret = set_bitmap(handle, bitmap);
if (s32Ret)
fprintf(stderr, "load_bitmap failed!Handle:%d\n", handle);
free(bitmap->pData);
return s32Ret;
}

void unload_region(unsigned int handle)
{
#ifdef __SIGMASTAR__
MI_RGN_ChnPort_t stChn;
#else
MPP_CHN_S stChn;
#endif
stChn.s32DevId = 0;
stChn.s32ChnId = 0;
#ifdef __SIGMASTAR__
stChn.eModId = E_MI_RGN_MODID_VPE;
stChn.s32OutputPortId = 1;
MI_RGN_DetachFromChn(handle, &stChn);
stChn.s32OutputPortId = 0;
MI_RGN_DetachFromChn(handle, &stChn);
int s32Ret = MI_RGN_Destroy(handle);
#else
stChn.enModId = HI_ID_VENC;
HI_MPI_RGN_DetachFromChn(handle, &stChn);
int s32Ret = HI_MPI_RGN_Destroy(handle);
#endif

if (s32Ret)
fprintf(stderr, "[%s:%d]RGN_Destroy failed with %#x %d!\n", __func__, __LINE__, s32Ret, handle);
}
Loading

0 comments on commit 52b4beb

Please sign in to comment.